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

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

Issue 17131002: Enables language tests for SIMMIPS. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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
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" 5 #include "vm/globals.h"
6 #if defined(TARGET_ARCH_MIPS) 6 #if defined(TARGET_ARCH_MIPS)
7 7
8 #include "vm/assembler.h" 8 #include "vm/assembler.h"
9 #include "vm/code_generator.h" 9 #include "vm/code_generator.h"
10 #include "vm/compiler.h" 10 #include "vm/compiler.h"
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after
88 // Retval is next to 1st argument. 88 // Retval is next to 1st argument.
89 __ delay_slot()->addiu(A3, A2, Immediate(kWordSize)); 89 __ delay_slot()->addiu(A3, A2, Immediate(kWordSize));
90 __ TraceSimMsg("CallToRuntimeStub return"); 90 __ TraceSimMsg("CallToRuntimeStub return");
91 91
92 // Reset exit frame information in Isolate structure. 92 // Reset exit frame information in Isolate structure.
93 __ sw(ZR, Address(CTX, Isolate::top_exit_frame_info_offset())); 93 __ sw(ZR, Address(CTX, Isolate::top_exit_frame_info_offset()));
94 94
95 // Load Context pointer from Isolate structure into A2. 95 // Load Context pointer from Isolate structure into A2.
96 __ lw(A2, Address(CTX, Isolate::top_context_offset())); 96 __ lw(A2, Address(CTX, Isolate::top_context_offset()));
97 97
98 // Reload NULLREG. 98 // Load null.
99 __ LoadImmediate(NULLREG, reinterpret_cast<intptr_t>(Object::null())); 99 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
100 100
101 // Reset Context pointer in Isolate structure. 101 // Reset Context pointer in Isolate structure.
102 __ sw(NULLREG, Address(CTX, Isolate::top_context_offset())); 102 __ sw(TMP, Address(CTX, Isolate::top_context_offset()));
103 103
104 // Cache Context pointer into CTX while executing Dart code. 104 // Cache Context pointer into CTX while executing Dart code.
105 __ mov(CTX, A2); 105 __ mov(CTX, A2);
106 106
107 __ mov(SP, FP); 107 __ mov(SP, FP);
108 __ lw(RA, Address(SP, 1 * kWordSize)); 108 __ lw(RA, Address(SP, 1 * kWordSize));
109 __ lw(FP, Address(SP, 0 * kWordSize)); 109 __ lw(FP, Address(SP, 0 * kWordSize));
110 __ Ret(); 110 __ Ret();
111 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); 111 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize));
112 } 112 }
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
195 // Call native function or redirection via simulator. 195 // Call native function or redirection via simulator.
196 __ jalr(T5); 196 __ jalr(T5);
197 __ TraceSimMsg("CallNativeCFunctionStub return"); 197 __ TraceSimMsg("CallNativeCFunctionStub return");
198 198
199 // Reset exit frame information in Isolate structure. 199 // Reset exit frame information in Isolate structure.
200 __ sw(ZR, Address(CTX, Isolate::top_exit_frame_info_offset())); 200 __ sw(ZR, Address(CTX, Isolate::top_exit_frame_info_offset()));
201 201
202 // Load Context pointer from Isolate structure into A2. 202 // Load Context pointer from Isolate structure into A2.
203 __ lw(A2, Address(CTX, Isolate::top_context_offset())); 203 __ lw(A2, Address(CTX, Isolate::top_context_offset()));
204 204
205 // Reload NULLREG. 205 // Load null.
206 __ LoadImmediate(NULLREG, reinterpret_cast<intptr_t>(Object::null())); 206 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
207 207
208 // Reset Context pointer in Isolate structure. 208 // Reset Context pointer in Isolate structure.
209 __ sw(NULLREG, Address(CTX, Isolate::top_context_offset())); 209 __ sw(TMP, Address(CTX, Isolate::top_context_offset()));
210 210
211 // Cache Context pointer into CTX while executing Dart code. 211 // Cache Context pointer into CTX while executing Dart code.
212 __ mov(CTX, A2); 212 __ mov(CTX, A2);
213 213
214 __ mov(SP, FP); 214 __ mov(SP, FP);
215 __ lw(RA, Address(SP, 1 * kWordSize)); 215 __ lw(RA, Address(SP, 1 * kWordSize));
216 __ lw(FP, Address(SP, 0 * kWordSize)); 216 __ lw(FP, Address(SP, 0 * kWordSize));
217 __ Ret(); 217 __ Ret();
218 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); 218 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize));
219 } 219 }
220 220
221 221
222 // Input parameters: 222 // Input parameters:
223 // S4: arguments descriptor array. 223 // S4: arguments descriptor array.
224 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 224 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
225 __ TraceSimMsg("CallStaticFunctionStub"); 225 __ TraceSimMsg("CallStaticFunctionStub");
226 __ EnterStubFrame(); 226 __ EnterStubFrame();
227 // Setup space on stack for return value and preserve arguments descriptor. 227 // Setup space on stack for return value and preserve arguments descriptor.
228 228
229 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 229 __ addiu(SP, SP, Immediate(-2 * kWordSize));
230 __ sw(S4, Address(SP, 1 * kWordSize)); 230 __ sw(S4, Address(SP, 1 * kWordSize));
231 __ sw(NULLREG, Address(SP, 0 * kWordSize)); 231 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
232 __ sw(TMP, Address(SP, 0 * kWordSize));
232 233
233 __ CallRuntime(kPatchStaticCallRuntimeEntry); 234 __ CallRuntime(kPatchStaticCallRuntimeEntry);
234 __ TraceSimMsg("CallStaticFunctionStub return"); 235 __ TraceSimMsg("CallStaticFunctionStub return");
235 236
236 // Get Code object result and restore arguments descriptor array. 237 // Get Code object result and restore arguments descriptor array.
237 __ lw(T0, Address(SP, 0 * kWordSize)); 238 __ lw(T0, Address(SP, 0 * kWordSize));
238 __ lw(S4, Address(SP, 1 * kWordSize)); 239 __ lw(S4, Address(SP, 1 * kWordSize));
239 __ addiu(SP, SP, Immediate(2 * kWordSize)); 240 __ addiu(SP, SP, Immediate(2 * kWordSize));
240 241
241 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); 242 __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
242 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag); 243 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag);
243 244
244 // Remove the stub frame as we are about to jump to the dart function. 245 // Remove the stub frame as we are about to jump to the dart function.
245 __ LeaveStubFrameAndReturn(T0); 246 __ LeaveStubFrameAndReturn(T0);
246 } 247 }
247 248
248 249
249 // Called from a static call only when an invalid code has been entered 250 // Called from a static call only when an invalid code has been entered
250 // (invalid because its function was optimized or deoptimized). 251 // (invalid because its function was optimized or deoptimized).
251 // S4: arguments descriptor array. 252 // S4: arguments descriptor array.
252 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 253 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
253 // Create a stub frame as we are pushing some objects on the stack before 254 // Create a stub frame as we are pushing some objects on the stack before
254 // calling into the runtime. 255 // calling into the runtime.
255 __ TraceSimMsg("FixCallersTarget"); 256 __ TraceSimMsg("FixCallersTarget");
256 __ EnterStubFrame(); 257 __ EnterStubFrame();
257 // Setup space on stack for return value and preserve arguments descriptor. 258 // Setup space on stack for return value and preserve arguments descriptor.
258 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 259 __ addiu(SP, SP, Immediate(-2 * kWordSize));
259 __ sw(S4, Address(SP, 1 * kWordSize)); 260 __ sw(S4, Address(SP, 1 * kWordSize));
260 __ sw(NULLREG, Address(SP, 0 * kWordSize)); 261 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
262 __ sw(TMP, Address(SP, 0 * kWordSize));
261 __ CallRuntime(kFixCallersTargetRuntimeEntry); 263 __ CallRuntime(kFixCallersTargetRuntimeEntry);
262 // Get Code object result and restore arguments descriptor array. 264 // Get Code object result and restore arguments descriptor array.
263 __ lw(T0, Address(SP, 0 * kWordSize)); 265 __ lw(T0, Address(SP, 0 * kWordSize));
264 __ lw(S4, Address(SP, 1 * kWordSize)); 266 __ lw(S4, Address(SP, 1 * kWordSize));
265 __ addiu(SP, SP, Immediate(2 * kWordSize)); 267 __ addiu(SP, SP, Immediate(2 * kWordSize));
266 268
267 // Jump to the dart function. 269 // Jump to the dart function.
268 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); 270 __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
269 __ AddImmediate(T0, T0, Instructions::HeaderSize() - kHeapObjectTag); 271 __ AddImmediate(T0, T0, Instructions::HeaderSize() - kHeapObjectTag);
270 272
271 // Remove the stub frame. 273 // Remove the stub frame.
272 __ LeaveStubFrameAndReturn(T0); 274 __ LeaveStubFrameAndReturn(T0);
273 } 275 }
274 276
275 277
276 // Input parameters: 278 // Input parameters:
277 // A1: Smi-tagged argument count, may be zero. 279 // A1: Smi-tagged argument count, may be zero.
278 // FP[kParamEndSlotFromFp + 1]: Last argument. 280 // FP[kParamEndSlotFromFp + 1]: Last argument.
279 static void PushArgumentsArray(Assembler* assembler) { 281 static void PushArgumentsArray(Assembler* assembler) {
280 __ TraceSimMsg("PushArgumentsArray"); 282 __ TraceSimMsg("PushArgumentsArray");
281 // Allocate array to store arguments of caller. 283 // Allocate array to store arguments of caller.
282 __ mov(A0, NULLREG); 284 __ LoadImmediate(A0, reinterpret_cast<intptr_t>(Object::null()));
283 // A0: Null element type for raw Array. 285 // A0: Null element type for raw Array.
284 // A1: Smi-tagged argument count, may be zero. 286 // A1: Smi-tagged argument count, may be zero.
285 __ BranchLink(&StubCode::AllocateArrayLabel()); 287 __ BranchLink(&StubCode::AllocateArrayLabel());
286 __ TraceSimMsg("PushArgumentsArray return"); 288 __ TraceSimMsg("PushArgumentsArray return");
287 // V0: newly allocated array. 289 // V0: newly allocated array.
288 // A1: Smi-tagged argument count, may be zero (was preserved by the stub). 290 // A1: Smi-tagged argument count, may be zero (was preserved by the stub).
289 __ Push(V0); // Array is in V0 and on top of stack. 291 __ Push(V0); // Array is in V0 and on top of stack.
290 __ sll(T1, A1, 1); 292 __ sll(T1, A1, 1);
291 __ addu(T1, FP, T1); 293 __ addu(T1, FP, T1);
292 __ AddImmediate(T1, kParamEndSlotFromFp * kWordSize); 294 __ AddImmediate(T1, kParamEndSlotFromFp * kWordSize);
(...skipping 29 matching lines...) Expand all
322 __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 324 __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
323 __ sll(TMP1, A1, 1); // A1 is Smi. 325 __ sll(TMP1, A1, 1); // A1 is Smi.
324 __ addu(TMP1, FP, TMP1); 326 __ addu(TMP1, FP, TMP1);
325 __ lw(T1, Address(TMP1, kParamEndSlotFromFp * kWordSize)); 327 __ lw(T1, Address(TMP1, kParamEndSlotFromFp * kWordSize));
326 328
327 // Push space for the return value. 329 // Push space for the return value.
328 // Push the receiver. 330 // Push the receiver.
329 // Push TMP1 data object. 331 // Push TMP1 data object.
330 // Push arguments descriptor array. 332 // Push arguments descriptor array.
331 __ addiu(SP, SP, Immediate(-4 * kWordSize)); 333 __ addiu(SP, SP, Immediate(-4 * kWordSize));
332 __ sw(NULLREG, Address(SP, 3 * kWordSize)); 334 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
335 __ sw(TMP, Address(SP, 3 * kWordSize));
333 __ sw(T1, Address(SP, 2 * kWordSize)); 336 __ sw(T1, Address(SP, 2 * kWordSize));
334 __ sw(S5, Address(SP, 1 * kWordSize)); 337 __ sw(S5, Address(SP, 1 * kWordSize));
335 __ sw(S4, Address(SP, 0 * kWordSize)); 338 __ sw(S4, Address(SP, 0 * kWordSize));
336 339
337 // A1: Smi-tagged arguments array length. 340 // A1: Smi-tagged arguments array length.
338 PushArgumentsArray(assembler); 341 PushArgumentsArray(assembler);
339 __ TraceSimMsg("InstanceFunctionLookupStub return"); 342 __ TraceSimMsg("InstanceFunctionLookupStub return");
340 343
341 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry); 344 __ CallRuntime(kInstanceFunctionLookupRuntimeEntry);
342 345
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 GenerateDeoptimizationSequence(assembler, true); // Preserve V0. 494 GenerateDeoptimizationSequence(assembler, true); // Preserve V0.
492 } 495 }
493 496
494 497
495 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) { 498 void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
496 GenerateDeoptimizationSequence(assembler, false); // Don't preserve V0. 499 GenerateDeoptimizationSequence(assembler, false); // Don't preserve V0.
497 } 500 }
498 501
499 502
500 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) { 503 void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
501 __ Unimplemented("MegamorphicMiss stub"); 504 __ EnterStubFrame();
502 return; 505
506 // Load the receiver.
507 __ lw(T2, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
508 __ sll(T2, T2, 1); // T2 is a Smi.
509 __ addu(TMP, FP, T2);
510 __ lw(T6, Address(TMP, kParamEndSlotFromFp * kWordSize));
511
512 // Preserve IC data and arguments descriptor.
513 __ addiu(SP, SP, Immediate(-6 * kWordSize));
514 __ sw(S5, Address(SP, 5 * kWordSize));
515 __ sw(S4, Address(SP, 4 * kWordSize));
516
517 // Push space for the return value.
518 // Push the receiver.
519 // Push IC data object.
520 // Push arguments descriptor array.
521 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
522 __ sw(TMP, Address(SP, 3 * kWordSize));
523 __ sw(T6, Address(SP, 2 * kWordSize));
524 __ sw(S5, Address(SP, 1 * kWordSize));
525 __ sw(S4, Address(SP, 0 * kWordSize));
526
527 __ CallRuntime(kMegamorphicCacheMissHandlerRuntimeEntry);
528
529 __ lw(T0, Address(SP, 3 * kWordSize)); // Get result.
530 __ lw(S4, Address(SP, 4 * kWordSize)); // Restore argument descriptor.
531 __ lw(S5, Address(SP, 5 * kWordSize)); // Restore IC data.
532 __ addiu(SP, SP, Immediate(6 * kWordSize));
533
534 __ LeaveStubFrame();
535
536 Label nonnull;
537 __ BranchNotEqual(T0, reinterpret_cast<int32_t>(Object::null()), &nonnull);
538 __ Branch(&StubCode::InstanceFunctionLookupLabel());
539 __ Bind(&nonnull);
540 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag);
541 __ jr(T0);
503 } 542 }
504 543
505 544
506 // Called for inline allocation of arrays. 545 // Called for inline allocation of arrays.
507 // Input parameters: 546 // Input parameters:
508 // RA: return address. 547 // RA: return address.
509 // A1: Array length as Smi. 548 // A1: Array length as Smi.
510 // A0: array element type (either NULL or an instantiated type). 549 // A0: array element type (either NULL or an instantiated type).
511 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved. 550 // NOTE: A1 cannot be clobbered here as the caller relies on it being saved.
512 // The newly allocated object is returned in V0. 551 // The newly allocated object is returned in V0.
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after
597 __ sw(T3, FieldAddress(V0, Array::tags_offset())); 636 __ sw(T3, FieldAddress(V0, Array::tags_offset()));
598 637
599 // Initialize all array elements to raw_null. 638 // Initialize all array elements to raw_null.
600 // V0: new object start as a tagged pointer. 639 // V0: new object start as a tagged pointer.
601 // T2: new object end address. 640 // T2: new object end address.
602 // A1: Array length as Smi. 641 // A1: Array length as Smi.
603 __ AddImmediate(T3, V0, Array::data_offset() - kHeapObjectTag); 642 __ AddImmediate(T3, V0, Array::data_offset() - kHeapObjectTag);
604 // T3: iterator which initially points to the start of the variable 643 // T3: iterator which initially points to the start of the variable
605 // data area to be initialized. 644 // data area to be initialized.
606 645
646 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
607 Label loop, loop_exit; 647 Label loop, loop_exit;
608 __ BranchUnsignedGreaterEqual(T3, T2, &loop_exit); 648 __ BranchUnsignedGreaterEqual(T3, T2, &loop_exit);
609 __ Bind(&loop); 649 __ Bind(&loop);
610 __ addiu(T3, T3, Immediate(kWordSize)); 650 __ addiu(T3, T3, Immediate(kWordSize));
611 __ bne(T3, T2, &loop); 651 __ bne(T3, T2, &loop);
612 __ delay_slot()->sw(NULLREG, Address(T3, -kWordSize)); 652 __ delay_slot()->sw(T7, Address(T3, -kWordSize));
613 __ Bind(&loop_exit); 653 __ Bind(&loop_exit);
614 654
615 // Done allocating and initializing the array. 655 // Done allocating and initializing the array.
616 // V0: new object. 656 // V0: new object.
617 // A1: Array length as Smi (preserved for the caller.) 657 // A1: Array length as Smi (preserved for the caller.)
618 __ Ret(); 658 __ Ret();
619 } 659 }
620 660
621 // Unable to allocate the array using the fast inline code, just call 661 // Unable to allocate the array using the fast inline code, just call
622 // into the runtime. 662 // into the runtime.
623 __ Bind(&slow_case); 663 __ Bind(&slow_case);
624 // Create a stub frame as we are pushing some objects on the stack before 664 // Create a stub frame as we are pushing some objects on the stack before
625 // calling into the runtime. 665 // calling into the runtime.
626 __ EnterStubFrame(); 666 __ EnterStubFrame();
627 // Setup space on stack for return value. 667 // Setup space on stack for return value.
628 // Push array length as Smi and element type. 668 // Push array length as Smi and element type.
629 __ addiu(SP, SP, Immediate(-3 * kWordSize)); 669 __ addiu(SP, SP, Immediate(-3 * kWordSize));
630 __ sw(NULLREG, Address(SP, 2 * kWordSize)); 670 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
671 __ sw(TMP, Address(SP, 2 * kWordSize));
631 __ sw(A1, Address(SP, 1 * kWordSize)); 672 __ sw(A1, Address(SP, 1 * kWordSize));
632 __ sw(T3, Address(SP, 0 * kWordSize)); 673 __ sw(A0, Address(SP, 0 * kWordSize));
633 __ CallRuntime(kAllocateArrayRuntimeEntry); 674 __ CallRuntime(kAllocateArrayRuntimeEntry);
634 __ TraceSimMsg("AllocateArrayStub return"); 675 __ TraceSimMsg("AllocateArrayStub return");
635 // Pop arguments; result is popped in IP. 676 // Pop arguments; result is popped in IP.
636 __ lw(TMP1, Address(SP, 2 * kWordSize)); 677 __ lw(V0, Address(SP, 2 * kWordSize));
637 __ lw(A1, Address(SP, 1 * kWordSize)); 678 __ lw(A1, Address(SP, 1 * kWordSize));
638 __ lw(T3, Address(SP, 0 * kWordSize)); 679 __ lw(A0, Address(SP, 0 * kWordSize));
639 __ addiu(SP, SP, Immediate(3 * kWordSize)); 680 __ addiu(SP, SP, Immediate(3 * kWordSize));
640 __ mov(V0, TMP1);
641 681
642 __ LeaveStubFrameAndReturn(); 682 __ LeaveStubFrameAndReturn();
643 } 683 }
644 684
645 685
646 // Input parameters: 686 // Input parameters:
647 // RA: return address. 687 // RA: return address.
648 // SP: address of last argument. 688 // SP: address of last argument.
649 // S4: Arguments descriptor array. 689 // S4: Arguments descriptor array.
650 // Return: V0. 690 // Return: V0.
651 // Note: The closure object is the first argument to the function being 691 // Note: The closure object is the first argument to the function being
652 // called, the stub accesses the closure from this location directly 692 // called, the stub accesses the closure from this location directly
653 // when trying to resolve the call. 693 // when trying to resolve the call.
654 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) { 694 void StubCode::GenerateCallClosureFunctionStub(Assembler* assembler) {
655 // Load num_args. 695 // Load num_args.
656 __ TraceSimMsg("GenerateCallClosureFunctionStub"); 696 __ TraceSimMsg("GenerateCallClosureFunctionStub");
657 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 697 __ lw(T0, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
658 __ LoadImmediate(TMP1, Smi::RawValue(1)); 698 __ LoadImmediate(TMP1, Smi::RawValue(1));
659 __ subu(T0, T0, TMP1); 699 __ subu(T0, T0, TMP1);
660 700
661 // Load closure object in T1. 701 // Load closure object in T1.
662 __ sll(T1, T0, 1); // T0 (num_args - 1) is a Smi. 702 __ sll(T1, T0, 1); // T0 (num_args - 1) is a Smi.
663 __ addu(T1, SP, T1); 703 __ addu(T1, SP, T1);
664 __ lw(T1, Address(T1)); 704 __ lw(T1, Address(T1));
665 705
666 // Verify that T1 is a closure by checking its class. 706 // Verify that T1 is a closure by checking its class.
667 Label not_closure; 707 Label not_closure;
668 708
709 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
710
669 // See if it is not a closure, but null object. 711 // See if it is not a closure, but null object.
670 __ beq(T1, NULLREG, &not_closure); 712 __ beq(T1, T7, &not_closure);
671 713
672 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); 714 __ andi(CMPRES, T1, Immediate(kSmiTagMask));
673 __ beq(CMPRES, ZR, &not_closure); // Not a closure, but a smi. 715 __ beq(CMPRES, ZR, &not_closure); // Not a closure, but a smi.
674 716
675 // Verify that the class of the object is a closure class by checking that 717 // Verify that the class of the object is a closure class by checking that
676 // class.signature_function() is not null. 718 // class.signature_function() is not null.
677 __ LoadClass(T0, T1); 719 __ LoadClass(T0, T1);
678 __ lw(T0, FieldAddress(T0, Class::signature_function_offset())); 720 __ lw(T0, FieldAddress(T0, Class::signature_function_offset()));
679 721
680 // See if actual class is not a closure class. 722 // See if actual class is not a closure class.
681 __ beq(T0, NULLREG, &not_closure); 723 __ beq(T0, T7, &not_closure);
682 724
683 // T0 is just the signature function. Load the actual closure function. 725 // T0 is just the signature function. Load the actual closure function.
684 __ lw(T2, FieldAddress(T1, Closure::function_offset())); 726 __ lw(T2, FieldAddress(T1, Closure::function_offset()));
685 727
686 // Load closure context in CTX; note that CTX has already been preserved. 728 // Load closure context in CTX; note that CTX has already been preserved.
687 __ lw(CTX, FieldAddress(T1, Closure::context_offset())); 729 __ lw(CTX, FieldAddress(T1, Closure::context_offset()));
688 730
689 Label function_compiled; 731 Label function_compiled;
690 // Load closure function code in T0. 732 // Load closure function code in T0.
691 __ lw(T0, FieldAddress(T2, Function::code_offset())); 733 __ lw(T0, FieldAddress(T2, Function::code_offset()));
692 __ bne(T0, NULLREG, &function_compiled); 734 __ bne(T0, T7, &function_compiled);
693 735
694 // Create a stub frame as we are pushing some objects on the stack before 736 // Create a stub frame as we are pushing some objects on the stack before
695 // calling into the runtime. 737 // calling into the runtime.
696 __ EnterStubFrame(); 738 __ EnterStubFrame();
697 739
698 // Preserve arguments descriptor array and read-only function object argument. 740 // Preserve arguments descriptor array and read-only function object argument.
699 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 741 __ addiu(SP, SP, Immediate(-2 * kWordSize));
700 __ sw(S4, Address(SP, 1 * kWordSize)); 742 __ sw(S4, Address(SP, 1 * kWordSize));
701 __ sw(T2, Address(SP, 0 * kWordSize)); 743 __ sw(T2, Address(SP, 0 * kWordSize));
702 __ CallRuntime(kCompileFunctionRuntimeEntry); 744 __ CallRuntime(kCompileFunctionRuntimeEntry);
(...skipping 21 matching lines...) Expand all
724 // returning here. 766 // returning here.
725 // If no call method exists, throw a NoSuchMethodError. 767 // If no call method exists, throw a NoSuchMethodError.
726 // T1: non-closure object. 768 // T1: non-closure object.
727 // S4: arguments descriptor array. 769 // S4: arguments descriptor array.
728 770
729 // Create a stub frame as we are pushing some objects on the stack before 771 // Create a stub frame as we are pushing some objects on the stack before
730 // calling into the runtime. 772 // calling into the runtime.
731 __ EnterStubFrame(); 773 __ EnterStubFrame();
732 774
733 // Setup space on stack for result from error reporting. 775 // Setup space on stack for result from error reporting.
734 __ addiu(SP, SP, Immediate(2 * kWordSize)); 776 __ addiu(SP, SP, Immediate(-2 * kWordSize));
735 // Arguments descriptor and raw null. 777 // Arguments descriptor and raw null.
736 __ sw(NULLREG, Address(SP, 1 * kWordSize)); 778 __ sw(T7, Address(SP, 1 * kWordSize));
737 __ sw(S4, Address(SP, 0 * kWordSize)); 779 __ sw(S4, Address(SP, 0 * kWordSize));
738 780
739 // Load smi-tagged arguments array length, including the non-closure. 781 // Load smi-tagged arguments array length, including the non-closure.
740 __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 782 __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
741 PushArgumentsArray(assembler); 783 PushArgumentsArray(assembler);
742 784
743 // Stack: 785 // Stack:
744 // TOS + 0: Argument array. 786 // TOS + 0: Argument array.
745 // TOS + 1: Arguments descriptor array. 787 // TOS + 1: Arguments descriptor array.
746 // TOS + 2: Place for result from the call. 788 // TOS + 2: Place for result from the call.
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
818 // Load arguments descriptor array into S4, which is passed to Dart code. 860 // Load arguments descriptor array into S4, which is passed to Dart code.
819 __ lw(S4, Address(A1, VMHandles::kOffsetOfRawPtrInHandle)); 861 __ lw(S4, Address(A1, VMHandles::kOffsetOfRawPtrInHandle));
820 862
821 // Load number of arguments into S5. 863 // Load number of arguments into S5.
822 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 864 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
823 __ SmiUntag(T1); 865 __ SmiUntag(T1);
824 866
825 // Compute address of 'arguments array' data area into A2. 867 // Compute address of 'arguments array' data area into A2.
826 __ lw(A2, Address(A2, VMHandles::kOffsetOfRawPtrInHandle)); 868 __ lw(A2, Address(A2, VMHandles::kOffsetOfRawPtrInHandle));
827 869
828 // Load the null Object into NULLREG for easy comparisons.
829 __ LoadImmediate(NULLREG, reinterpret_cast<intptr_t>(Object::null()));
830
831 // Set up arguments for the Dart call. 870 // Set up arguments for the Dart call.
832 Label push_arguments; 871 Label push_arguments;
833 Label done_push_arguments; 872 Label done_push_arguments;
834 __ beq(T1, ZR, &done_push_arguments); // check if there are arguments. 873 __ beq(T1, ZR, &done_push_arguments); // check if there are arguments.
835 __ delay_slot()->addiu(A2, A2, 874 __ delay_slot()->addiu(A2, A2,
836 Immediate(Array::data_offset() - kHeapObjectTag)); 875 Immediate(Array::data_offset() - kHeapObjectTag));
837 __ mov(A1, ZR); 876 __ mov(A1, ZR);
838 __ Bind(&push_arguments); 877 __ Bind(&push_arguments);
839 __ lw(A3, Address(A2)); 878 __ lw(A3, Address(A2));
840 __ Push(A3); 879 __ Push(A3);
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
953 __ sw(T1, FieldAddress(V0, Context::num_variables_offset())); 992 __ sw(T1, FieldAddress(V0, Context::num_variables_offset()));
954 993
955 // Setup isolate field. 994 // Setup isolate field.
956 // Load Isolate pointer from Context structure into R2. 995 // Load Isolate pointer from Context structure into R2.
957 // V0: new object. 996 // V0: new object.
958 // T1: number of context variables. 997 // T1: number of context variables.
959 __ lw(T2, FieldAddress(CTX, Context::isolate_offset())); 998 __ lw(T2, FieldAddress(CTX, Context::isolate_offset()));
960 // T2: isolate, not an object. 999 // T2: isolate, not an object.
961 __ sw(T2, FieldAddress(V0, Context::isolate_offset())); 1000 __ sw(T2, FieldAddress(V0, Context::isolate_offset()));
962 1001
1002 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
1003
963 // Initialize the context variables. 1004 // Initialize the context variables.
964 // V0: new object. 1005 // V0: new object.
965 // T1: number of context variables. 1006 // T1: number of context variables.
966 Label loop, loop_exit; 1007 Label loop, loop_exit;
967 __ blez(T1, &loop_exit); 1008 __ blez(T1, &loop_exit);
968 // Setup the parent field. 1009 // Setup the parent field.
969 __ delay_slot()->sw(NULLREG, FieldAddress(V0, Context::parent_offset())); 1010 __ delay_slot()->sw(T7, FieldAddress(V0, Context::parent_offset()));
970 __ AddImmediate(T3, V0, Context::variable_offset(0) - kHeapObjectTag); 1011 __ AddImmediate(T3, V0, Context::variable_offset(0) - kHeapObjectTag);
971 __ sll(T1, T1, 2); 1012 __ sll(T1, T1, 2);
972 __ Bind(&loop); 1013 __ Bind(&loop);
973 __ addiu(T1, T1, Immediate(-kWordSize)); 1014 __ addiu(T1, T1, Immediate(-kWordSize));
974 __ addu(TMP1, T3, T1); 1015 __ addu(TMP1, T3, T1);
975 __ bgtz(T1, &loop); 1016 __ bgtz(T1, &loop);
976 __ delay_slot()->sw(NULLREG, Address(TMP1)); 1017 __ delay_slot()->sw(T7, Address(TMP1));
977 __ Bind(&loop_exit); 1018 __ Bind(&loop_exit);
978 1019
979 // Done allocating and initializing the context. 1020 // Done allocating and initializing the context.
980 // V0: new object. 1021 // V0: new object.
981 __ Ret(); 1022 __ Ret();
982 1023
983 __ Bind(&slow_case); 1024 __ Bind(&slow_case);
984 } 1025 }
985 // Create a stub frame as we are pushing some objects on the stack before 1026 // Create a stub frame as we are pushing some objects on the stack before
986 // calling into the runtime. 1027 // calling into the runtime.
987 __ EnterStubFrame(); 1028 __ EnterStubFrame();
988 // Setup space on stack for return value. 1029 // Setup space on stack for return value.
989 __ SmiTag(T1); 1030 __ SmiTag(T1);
990 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1031 __ addiu(SP, SP, Immediate(-2 * kWordSize));
991 __ sw(NULLREG, Address(SP, 1 * kWordSize)); 1032 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
1033 __ sw(TMP, Address(SP, 1 * kWordSize)); // Store null.
992 __ sw(T1, Address(SP, 0 * kWordSize)); 1034 __ sw(T1, Address(SP, 0 * kWordSize));
993 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context. 1035 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context.
994 __ lw(V0, Address(SP, 1 * kWordSize)); // Get the new context. 1036 __ lw(V0, Address(SP, 1 * kWordSize)); // Get the new context.
995 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Pop argument and return. 1037 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Pop argument and return.
996 1038
997 // V0: new object 1039 // V0: new object
998 // Restore the frame pointer. 1040 // Restore the frame pointer.
999 __ LeaveStubFrameAndReturn(); 1041 __ LeaveStubFrameAndReturn();
1000 } 1042 }
1001 1043
(...skipping 163 matching lines...) Expand 10 before | Expand all | Expand 10 after
1165 // T3: next object start. 1207 // T3: next object start.
1166 // T1: new object type arguments (if is_cls_parameterized). 1208 // T1: new object type arguments (if is_cls_parameterized).
1167 // Set the tags. 1209 // Set the tags.
1168 uword tags = 0; 1210 uword tags = 0;
1169 tags = RawObject::SizeTag::update(instance_size, tags); 1211 tags = RawObject::SizeTag::update(instance_size, tags);
1170 ASSERT(cls.id() != kIllegalCid); 1212 ASSERT(cls.id() != kIllegalCid);
1171 tags = RawObject::ClassIdTag::update(cls.id(), tags); 1213 tags = RawObject::ClassIdTag::update(cls.id(), tags);
1172 __ LoadImmediate(T0, tags); 1214 __ LoadImmediate(T0, tags);
1173 __ sw(T0, Address(T2, Instance::tags_offset())); 1215 __ sw(T0, Address(T2, Instance::tags_offset()));
1174 1216
1217 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
1218
1175 // Initialize the remaining words of the object. 1219 // Initialize the remaining words of the object.
1176 // T2: new object start. 1220 // T2: new object start.
1177 // T3: next object start. 1221 // T3: next object start.
1178 // T1: new object type arguments (if is_cls_parameterized). 1222 // T1: new object type arguments (if is_cls_parameterized).
1179 // First try inlining the initialization without a loop. 1223 // First try inlining the initialization without a loop.
1180 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1224 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1181 // Check if the object contains any non-header fields. 1225 // Check if the object contains any non-header fields.
1182 // Small objects are initialized using a consecutive set of writes. 1226 // Small objects are initialized using a consecutive set of writes.
1183 for (intptr_t current_offset = sizeof(RawObject); 1227 for (intptr_t current_offset = sizeof(RawObject);
1184 current_offset < instance_size; 1228 current_offset < instance_size;
1185 current_offset += kWordSize) { 1229 current_offset += kWordSize) {
1186 __ sw(NULLREG, Address(T2, current_offset)); 1230 __ sw(T7, Address(T2, current_offset));
1187 } 1231 }
1188 } else { 1232 } else {
1189 __ addiu(T4, T2, Immediate(sizeof(RawObject))); 1233 __ addiu(T4, T2, Immediate(sizeof(RawObject)));
1190 // Loop until the whole object is initialized. 1234 // Loop until the whole object is initialized.
1191 // T2: new object. 1235 // T2: new object.
1192 // T3: next object start. 1236 // T3: next object start.
1193 // T4: next word to be initialized. 1237 // T4: next word to be initialized.
1194 // T1: new object type arguments (if is_cls_parameterized). 1238 // T1: new object type arguments (if is_cls_parameterized).
1195 Label loop, loop_exit; 1239 Label loop, loop_exit;
1196 __ BranchUnsignedGreaterEqual(T4, T3, &loop_exit); 1240 __ BranchUnsignedGreaterEqual(T4, T3, &loop_exit);
1197 __ Bind(&loop); 1241 __ Bind(&loop);
1198 __ addiu(T4, T4, Immediate(kWordSize)); 1242 __ addiu(T4, T4, Immediate(kWordSize));
1199 __ bne(T4, T3, &loop); 1243 __ bne(T4, T3, &loop);
1200 __ delay_slot()->sw(NULLREG, Address(T4, -kWordSize)); 1244 __ delay_slot()->sw(T7, Address(T4, -kWordSize));
1201 __ Bind(&loop_exit); 1245 __ Bind(&loop_exit);
1202 } 1246 }
1203 if (is_cls_parameterized) { 1247 if (is_cls_parameterized) {
1204 // R1: new object type arguments. 1248 // R1: new object type arguments.
1205 // Set the type arguments in the new object. 1249 // Set the type arguments in the new object.
1206 __ sw(T1, Address(T2, cls.type_arguments_field_offset())); 1250 __ sw(T1, Address(T2, cls.type_arguments_field_offset()));
1207 } 1251 }
1208 // Done allocating and initializing the instance. 1252 // Done allocating and initializing the instance.
1209 // T2: new object still missing its heap tag. 1253 // T2: new object still missing its heap tag.
1210 __ Ret(); 1254 __ Ret();
1211 __ delay_slot()->addiu(V0, T2, Immediate(kHeapObjectTag)); 1255 __ delay_slot()->addiu(V0, T2, Immediate(kHeapObjectTag));
1212 1256
1213 __ Bind(&slow_case); 1257 __ Bind(&slow_case);
1214 } 1258 }
1215 if (is_cls_parameterized) { 1259 if (is_cls_parameterized) {
1216 __ lw(T1, Address(SP, 1 * kWordSize)); 1260 __ lw(T1, Address(SP, 1 * kWordSize));
1217 __ lw(T0, Address(SP, 0 * kWordSize)); 1261 __ lw(T0, Address(SP, 0 * kWordSize));
1218 } 1262 }
1219 // Create a stub frame as we are pushing some objects on the stack before 1263 // Create a stub frame as we are pushing some objects on the stack before
1220 // calling into the runtime. 1264 // calling into the runtime.
1221 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. 1265 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime.
1222 __ LoadObject(TMP1, cls); 1266 __ LoadObject(TMP1, cls);
1223 1267
1224 __ addiu(SP, SP, Immediate(-4 * kWordSize)); 1268 __ addiu(SP, SP, Immediate(-4 * kWordSize));
1225 // Space on stack for return value. 1269 // Space on stack for return value.
1226 __ sw(NULLREG, Address(SP, 3 * kWordSize)); 1270 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
1271 __ sw(T7, Address(SP, 3 * kWordSize));
1227 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Class of object to be allocated. 1272 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Class of object to be allocated.
1228 1273
1229 if (is_cls_parameterized) { 1274 if (is_cls_parameterized) {
1230 // Push type arguments of object to be allocated and of instantiator. 1275 // Push type arguments of object to be allocated and of instantiator.
1231 __ sw(T1, Address(SP, 1 * kWordSize)); 1276 __ sw(T1, Address(SP, 1 * kWordSize));
1232 __ sw(T0, Address(SP, 0 * kWordSize)); 1277 __ sw(T0, Address(SP, 0 * kWordSize));
1233 } else { 1278 } else {
1234 // Push null type arguments and kNoInstantiator. 1279 // Push null type arguments and kNoInstantiator.
1235 __ LoadImmediate(T1, Smi::RawValue(StubCode::kNoInstantiator)); 1280 __ LoadImmediate(T1, Smi::RawValue(StubCode::kNoInstantiator));
1236 __ sw(NULLREG, Address(SP, 1 * kWordSize)); 1281 __ sw(T7, Address(SP, 1 * kWordSize));
1237 __ sw(T1, Address(SP, 0 * kWordSize)); 1282 __ sw(T1, Address(SP, 0 * kWordSize));
1238 } 1283 }
1239 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. 1284 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object.
1240 __ TraceSimMsg("AllocationStubForClass return"); 1285 __ TraceSimMsg("AllocationStubForClass return");
1241 // Pop result (newly allocated object). 1286 // Pop result (newly allocated object).
1242 __ lw(V0, Address(SP, 3 * kWordSize)); 1287 __ lw(V0, Address(SP, 3 * kWordSize));
1243 __ addiu(SP, SP, Immediate(4 * kWordSize)); // Pop arguments. 1288 __ addiu(SP, SP, Immediate(4 * kWordSize)); // Pop arguments.
1244 // V0: new object 1289 // V0: new object
1245 // Restore the frame pointer and return. 1290 // Restore the frame pointer and return.
1246 __ LeaveStubFrameAndReturn(RA, true); 1291 __ LeaveStubFrameAndReturn(RA, true);
(...skipping 10 matching lines...) Expand all
1257 ASSERT(func.IsClosureFunction()); 1302 ASSERT(func.IsClosureFunction());
1258 const bool is_implicit_static_closure = 1303 const bool is_implicit_static_closure =
1259 func.IsImplicitStaticClosureFunction(); 1304 func.IsImplicitStaticClosureFunction();
1260 const bool is_implicit_instance_closure = 1305 const bool is_implicit_instance_closure =
1261 func.IsImplicitInstanceClosureFunction(); 1306 func.IsImplicitInstanceClosureFunction();
1262 const Class& cls = Class::ZoneHandle(func.signature_class()); 1307 const Class& cls = Class::ZoneHandle(func.signature_class());
1263 const bool has_type_arguments = cls.HasTypeArguments(); 1308 const bool has_type_arguments = cls.HasTypeArguments();
1264 1309
1265 __ TraceSimMsg("AllocationStubForClosure"); 1310 __ TraceSimMsg("AllocationStubForClosure");
1266 __ EnterStubFrame(true); // Uses pool pointer to refer to function. 1311 __ EnterStubFrame(true); // Uses pool pointer to refer to function.
1267 const intptr_t kTypeArgumentsFPOffset = 4 * kWordSize; 1312 const intptr_t kTypeArgumentsFPOffset = 3 * kWordSize;
1268 const intptr_t kReceiverFPOffset = 5 * kWordSize; 1313 const intptr_t kReceiverFPOffset = 4 * kWordSize;
1269 const intptr_t closure_size = Closure::InstanceSize(); 1314 const intptr_t closure_size = Closure::InstanceSize();
1270 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver. 1315 const intptr_t context_size = Context::InstanceSize(1); // Captured receiver.
1271 if (FLAG_inline_alloc && 1316 if (FLAG_inline_alloc &&
1272 Heap::IsAllocatableInNewSpace(closure_size + context_size)) { 1317 Heap::IsAllocatableInNewSpace(closure_size + context_size)) {
1273 Label slow_case; 1318 Label slow_case;
1274 Heap* heap = Isolate::Current()->heap(); 1319 Heap* heap = Isolate::Current()->heap();
1275 __ LoadImmediate(T5, heap->TopAddress()); 1320 __ LoadImmediate(T5, heap->TopAddress());
1276 __ lw(T2, Address(T5)); 1321 __ lw(T2, Address(T5));
1277 __ AddImmediate(T3, T2, closure_size); 1322 __ AddImmediate(T3, T2, closure_size);
1278 if (is_implicit_instance_closure) { 1323 if (is_implicit_instance_closure) {
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
1330 1375
1331 // Set number of variables field to 1 (for captured receiver). 1376 // Set number of variables field to 1 (for captured receiver).
1332 __ LoadImmediate(T0, 1); 1377 __ LoadImmediate(T0, 1);
1333 __ sw(T0, Address(T4, Context::num_variables_offset())); 1378 __ sw(T0, Address(T4, Context::num_variables_offset()));
1334 1379
1335 // Set isolate field to isolate of current context. 1380 // Set isolate field to isolate of current context.
1336 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); 1381 __ lw(T0, FieldAddress(CTX, Context::isolate_offset()));
1337 __ sw(T0, Address(T4, Context::isolate_offset())); 1382 __ sw(T0, Address(T4, Context::isolate_offset()));
1338 1383
1339 // Set the parent to null. 1384 // Set the parent to null.
1340 __ sw(NULLREG, Address(T4, Context::parent_offset())); 1385 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
1386 __ sw(TMP, Address(T4, Context::parent_offset()));
1341 1387
1342 // Initialize the context variable to the receiver. 1388 // Initialize the context variable to the receiver.
1343 __ lw(T0, Address(FP, kReceiverFPOffset)); 1389 __ lw(T0, Address(FP, kReceiverFPOffset));
1344 __ sw(T0, Address(T4, Context::variable_offset(0))); 1390 __ sw(T0, Address(T4, Context::variable_offset(0)));
1345 1391
1346 // Set the newly allocated context in the newly allocated closure. 1392 // Set the newly allocated context in the newly allocated closure.
1347 __ AddImmediate(T1, T4, kHeapObjectTag); 1393 __ AddImmediate(T1, T4, kHeapObjectTag);
1348 __ sw(T1, Address(T2, Closure::context_offset())); 1394 __ sw(T1, Address(T2, Closure::context_offset()));
1349 } else { 1395 } else {
1350 __ sw(CTX, Address(T2, Closure::context_offset())); 1396 __ sw(CTX, Address(T2, Closure::context_offset()));
(...skipping 12 matching lines...) Expand all
1363 __ Bind(&slow_case); 1409 __ Bind(&slow_case);
1364 } 1410 }
1365 1411
1366 // If it's an implicit static closure we need 2 stack slots. Otherwise, 1412 // If it's an implicit static closure we need 2 stack slots. Otherwise,
1367 // If it's an implicit instance closure we need 4 stack slots, o/w only 3. 1413 // If it's an implicit instance closure we need 4 stack slots, o/w only 3.
1368 int num_slots = 2; 1414 int num_slots = 2;
1369 if (!is_implicit_static_closure) { 1415 if (!is_implicit_static_closure) {
1370 num_slots = is_implicit_instance_closure ? 4 : 3; 1416 num_slots = is_implicit_instance_closure ? 4 : 3;
1371 } 1417 }
1372 __ addiu(SP, SP, Immediate(-num_slots * kWordSize)); 1418 __ addiu(SP, SP, Immediate(-num_slots * kWordSize));
1419 // Setup space on stack for return value.
1420 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
1421 __ sw(T7, Address(SP, (num_slots - 1) * kWordSize));
1373 __ LoadObject(TMP1, func); 1422 __ LoadObject(TMP1, func);
1374 // Setup space on stack for return value.
1375 __ sw(NULLREG, Address(SP, (num_slots - 1) * kWordSize));
1376 __ sw(TMP1, Address(SP, (num_slots - 2) * kWordSize)); 1423 __ sw(TMP1, Address(SP, (num_slots - 2) * kWordSize));
1377 if (is_implicit_static_closure) { 1424 if (is_implicit_static_closure) {
1378 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry); 1425 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry);
1379 __ TraceSimMsg("AllocationStubForClosure return"); 1426 __ TraceSimMsg("AllocationStubForClosure return");
1380 } else { 1427 } else {
1428 __ mov(T2, T7);
1381 if (is_implicit_instance_closure) { 1429 if (is_implicit_instance_closure) {
1382 __ lw(T1, Address(FP, kReceiverFPOffset)); 1430 __ lw(T1, Address(FP, kReceiverFPOffset));
1383 __ sw(T1, Address(SP, (num_slots - 3) * kWordSize)); // Receiver. 1431 __ sw(T1, Address(SP, (num_slots - 3) * kWordSize)); // Receiver.
1384 __ sw(NULLREG, Address(SP, (num_slots - 4) * kWordSize)); // Push null.
1385 } 1432 }
1386 if (has_type_arguments) { 1433 if (has_type_arguments) {
1387 __ lw(V0, Address(FP, kTypeArgumentsFPOffset)); 1434 __ lw(T2, Address(FP, kTypeArgumentsFPOffset));
1388 // Push type arguments of closure.
1389 __ sw(V0, Address(SP, (num_slots - 3) * kWordSize));
1390 } 1435 }
1436 __ sw(T2, Address(SP, 0 * kWordSize));
1391 1437
1392 if (is_implicit_instance_closure) { 1438 if (is_implicit_instance_closure) {
1393 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry); 1439 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry);
1394 __ TraceSimMsg("AllocationStubForClosure return"); 1440 __ TraceSimMsg("AllocationStubForClosure return");
1395 } else { 1441 } else {
1396 ASSERT(func.IsNonImplicitClosureFunction()); 1442 ASSERT(func.IsNonImplicitClosureFunction());
1397 __ CallRuntime(kAllocateClosureRuntimeEntry); 1443 __ CallRuntime(kAllocateClosureRuntimeEntry);
1398 __ TraceSimMsg("AllocationStubForClosure return"); 1444 __ TraceSimMsg("AllocationStubForClosure return");
1399 } 1445 }
1400 } 1446 }
1401 __ lw(V0, Address(SP, (num_slots - 1) * kWordSize)); // Pop function object. 1447 __ lw(V0, Address(SP, (num_slots - 1) * kWordSize)); // Pop function object.
1402 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); 1448 __ addiu(SP, SP, Immediate(num_slots * kWordSize));
1403 1449
1404 // V0: new object 1450 // V0: new object
1405 // Restore the frame pointer. 1451 // Restore the frame pointer.
1406 __ LeaveStubFrameAndReturn(RA, true); 1452 __ LeaveStubFrameAndReturn(RA, true);
1407 } 1453 }
1408 1454
1409 1455
1456 // The target function was not found, so invoke method
1457 // "dynamic noSuchMethod(Invocation invocation)".
1458 // S5: inline cache data object.
1459 // S4: arguments descriptor array.
1410 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) { 1460 void StubCode::GenerateCallNoSuchMethodFunctionStub(Assembler* assembler) {
1411 __ Unimplemented("CallNoSuchMethodFunction stub"); 1461 __ EnterStubFrame();
1462
1463 // Load the receiver.
1464 __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
1465 __ sll(TMP, A1, 1); // A1 is a Smi.
1466 __ addu(TMP, FP, TMP);
1467 __ lw(T6, Address(TMP, kParamEndSlotFromFp * kWordSize));
1468
1469 // Push space for the return value.
1470 // Push the receiver.
1471 // Push IC data object.
1472 // Push arguments descriptor array.
1473 __ addiu(SP, SP, Immediate(-4 * kWordSize));
1474 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
1475 __ sw(TMP, Address(SP, 3 * kWordSize));
1476 __ sw(T6, Address(SP, 2 * kWordSize));
1477 __ sw(S5, Address(SP, 1 * kWordSize));
1478 __ sw(S4, Address(SP, 0 * kWordSize));
1479
1480 // A1: Smi-tagged arguments array length.
1481 PushArgumentsArray(assembler);
1482
1483 __ CallRuntime(kInvokeNoSuchMethodFunctionRuntimeEntry);
1484
1485 __ lw(V0, Address(SP, 4 * kWordSize)); // Get result into V0.
1486 __ LeaveStubFrameAndReturn();
1412 } 1487 }
1413 1488
1414 1489
1415 // T0: function object. 1490 // T0: function object.
1416 // S5: inline cache data object. 1491 // S5: inline cache data object.
1417 // S4: arguments descriptor array. 1492 // S4: arguments descriptor array.
1418 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { 1493 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
1419 __ TraceSimMsg("OptimizedUsageCounterIncrement"); 1494 __ TraceSimMsg("OptimizedUsageCounterIncrement");
1420 Register ic_reg = S5; 1495 Register ic_reg = S5;
1421 Register func_reg = T0; 1496 Register func_reg = T0;
(...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after
1578 // T1: address of receiver. 1653 // T1: address of receiver.
1579 // Create a stub frame as we are pushing some objects on the stack before 1654 // Create a stub frame as we are pushing some objects on the stack before
1580 // calling into the runtime. 1655 // calling into the runtime.
1581 __ EnterStubFrame(); 1656 __ EnterStubFrame();
1582 // Preserve IC data object and arguments descriptor array and 1657 // Preserve IC data object and arguments descriptor array and
1583 // setup space on stack for result (target code object). 1658 // setup space on stack for result (target code object).
1584 int num_slots = num_args + 5; 1659 int num_slots = num_args + 5;
1585 __ addiu(SP, SP, Immediate(-num_slots * kWordSize)); 1660 __ addiu(SP, SP, Immediate(-num_slots * kWordSize));
1586 __ sw(S5, Address(SP, (num_slots - 1) * kWordSize)); 1661 __ sw(S5, Address(SP, (num_slots - 1) * kWordSize));
1587 __ sw(S4, Address(SP, (num_slots - 2) * kWordSize)); 1662 __ sw(S4, Address(SP, (num_slots - 2) * kWordSize));
1588 __ sw(NULLREG, Address(SP, (num_slots - 3) * kWordSize)); 1663 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
1664 __ sw(TMP, Address(SP, (num_slots - 3) * kWordSize));
1589 // Push call arguments. 1665 // Push call arguments.
1590 for (intptr_t i = 0; i < num_args; i++) { 1666 for (intptr_t i = 0; i < num_args; i++) {
1591 __ lw(TMP1, Address(T1, -i * kWordSize)); 1667 __ lw(TMP1, Address(T1, -i * kWordSize));
1592 __ sw(TMP1, Address(SP, (num_slots - i - 4) * kWordSize)); 1668 __ sw(TMP1, Address(SP, (num_slots - i - 4) * kWordSize));
1593 } 1669 }
1594 // Pass IC data object and arguments descriptor array. 1670 // Pass IC data object and arguments descriptor array.
1595 __ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize)); 1671 __ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize));
1596 __ sw(S4, Address(SP, (num_slots - num_args - 5) * kWordSize)); 1672 __ sw(S4, Address(SP, (num_slots - num_args - 5) * kWordSize));
1597 1673
1598 if (num_args == 1) { 1674 if (num_args == 1) {
1599 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); 1675 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
1600 } else if (num_args == 2) { 1676 } else if (num_args == 2) {
1601 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); 1677 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry);
1602 } else if (num_args == 3) { 1678 } else if (num_args == 3) {
1603 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); 1679 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry);
1604 } else { 1680 } else {
1605 UNIMPLEMENTED(); 1681 UNIMPLEMENTED();
1606 } 1682 }
1607 __ TraceSimMsg("NArgsCheckInlineCacheStub return"); 1683 __ TraceSimMsg("NArgsCheckInlineCacheStub return");
1608 // Pop returned code object into T3 (null if not found). 1684 // Pop returned code object into T3 (null if not found).
1609 // Restore arguments descriptor array and IC data array. 1685 // Restore arguments descriptor array and IC data array.
1610 __ lw(T3, Address(SP, (num_slots - 3) * kWordSize)); 1686 __ lw(T3, Address(SP, (num_slots - 3) * kWordSize));
1611 __ lw(S4, Address(SP, (num_slots - 2) * kWordSize)); 1687 __ lw(S4, Address(SP, (num_slots - 2) * kWordSize));
1612 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize)); 1688 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize));
1613 // Remove the call arguments pushed earlier, including the IC data object 1689 // Remove the call arguments pushed earlier, including the IC data object
1614 // and the arguments descriptor array. 1690 // and the arguments descriptor array.
1615 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); 1691 __ addiu(SP, SP, Immediate(num_slots * kWordSize));
1616 __ LeaveStubFrame(); 1692 __ LeaveStubFrame();
1617 Label call_target_function; 1693 Label call_target_function;
1618 __ bne(T3, NULLREG, &call_target_function); 1694 __ BranchNotEqual(T3, reinterpret_cast<int32_t>(Object::null()),
1695 &call_target_function);
1619 1696
1620 // NoSuchMethod or closure. 1697 // NoSuchMethod or closure.
1621 // Mark IC call that it may be a closure call that does not collect 1698 // Mark IC call that it may be a closure call that does not collect
1622 // type feedback. 1699 // type feedback.
1623 __ LoadImmediate(TMP1, 1); 1700 __ LoadImmediate(TMP1, 1);
1624 __ Branch(&StubCode::InstanceFunctionLookupLabel()); 1701 __ Branch(&StubCode::InstanceFunctionLookupLabel());
1625 __ delay_slot()->sb(TMP1, FieldAddress(S5, ICData::is_closure_call_offset())); 1702 __ delay_slot()->sb(TMP1, FieldAddress(S5, ICData::is_closure_call_offset()));
1626 1703
1627 __ Bind(&found); 1704 __ Bind(&found);
1628 // T0: Pointer to an IC data check group. 1705 // T0: Pointer to an IC data check group.
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
1730 // RA: return address (Dart code). 1807 // RA: return address (Dart code).
1731 // S4: Arguments descriptor array. 1808 // S4: Arguments descriptor array.
1732 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { 1809 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
1733 __ TraceSimMsg("BreakpointStaticStub"); 1810 __ TraceSimMsg("BreakpointStaticStub");
1734 // Create a stub frame as we are pushing some objects on the stack before 1811 // Create a stub frame as we are pushing some objects on the stack before
1735 // calling into the runtime. 1812 // calling into the runtime.
1736 __ EnterStubFrame(); 1813 __ EnterStubFrame();
1737 // Preserve arguments descriptor and make room for result. 1814 // Preserve arguments descriptor and make room for result.
1738 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1815 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1739 __ sw(S4, Address(SP, 1 * kWordSize)); 1816 __ sw(S4, Address(SP, 1 * kWordSize));
1740 __ sw(NULLREG, Address(SP, 0 * kWordSize)); 1817 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
1818 __ sw(TMP, Address(SP, 0 * kWordSize));
1741 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); 1819 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
1742 // Pop code object result and restore arguments descriptor. 1820 // Pop code object result and restore arguments descriptor.
1743 __ lw(T0, Address(SP, 0 * kWordSize)); 1821 __ lw(T0, Address(SP, 0 * kWordSize));
1744 __ lw(S4, Address(SP, 1 * kWordSize)); 1822 __ lw(S4, Address(SP, 1 * kWordSize));
1745 __ addiu(SP, SP, Immediate(2 * kWordSize)); 1823 __ addiu(SP, SP, Immediate(2 * kWordSize));
1746 __ LeaveStubFrame(); 1824 __ LeaveStubFrame();
1747 1825
1748 // Now call the static function. The breakpoint handler function 1826 // Now call the static function. The breakpoint handler function
1749 // ensures that the call target is compiled. 1827 // ensures that the call target is compiled.
1750 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); 1828 __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1830 } 1908 }
1831 __ LoadClassId(T0, A0); 1909 __ LoadClassId(T0, A0);
1832 // A0: instance. 1910 // A0: instance.
1833 // A1: instantiator type arguments or NULL. 1911 // A1: instantiator type arguments or NULL.
1834 // A2: SubtypeTestCache. 1912 // A2: SubtypeTestCache.
1835 // T0: instance class id. 1913 // T0: instance class id.
1836 // T1: instance type arguments (null if none), used only if n > 1. 1914 // T1: instance type arguments (null if none), used only if n > 1.
1837 __ lw(T2, FieldAddress(A2, SubtypeTestCache::cache_offset())); 1915 __ lw(T2, FieldAddress(A2, SubtypeTestCache::cache_offset()));
1838 __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag); 1916 __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag);
1839 1917
1918 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
1919
1840 Label loop, found, not_found, next_iteration; 1920 Label loop, found, not_found, next_iteration;
1841 // T0: instance class id. 1921 // T0: instance class id.
1842 // T1: instance type arguments. 1922 // T1: instance type arguments.
1843 // T2: Entry start. 1923 // T2: Entry start.
1924 // T7: null.
1844 __ SmiTag(T0); 1925 __ SmiTag(T0);
1845 __ Bind(&loop); 1926 __ Bind(&loop);
1846 __ lw(T3, Address(T2, kWordSize * SubtypeTestCache::kInstanceClassId)); 1927 __ lw(T3, Address(T2, kWordSize * SubtypeTestCache::kInstanceClassId));
1847 __ beq(T3, NULLREG, &not_found); 1928 __ beq(T3, T7, &not_found);
1848 1929
1849 if (n == 1) { 1930 if (n == 1) {
1850 __ beq(T3, T0, &found); 1931 __ beq(T3, T0, &found);
1851 } else { 1932 } else {
1852 __ bne(T3, T0, &next_iteration); 1933 __ bne(T3, T0, &next_iteration);
1853 __ lw(T3, 1934 __ lw(T3,
1854 Address(T2, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); 1935 Address(T2, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
1855 if (n == 2) { 1936 if (n == 2) {
1856 __ beq(T3, T1, &found); 1937 __ beq(T3, T1, &found);
1857 } else { 1938 } else {
1858 __ bne(T3, T1, &next_iteration); 1939 __ bne(T3, T1, &next_iteration);
1859 __ lw(T3, Address(T2, kWordSize * 1940 __ lw(T3, Address(T2, kWordSize *
1860 SubtypeTestCache::kInstantiatorTypeArguments)); 1941 SubtypeTestCache::kInstantiatorTypeArguments));
1861 __ beq(T3, A1, &found); 1942 __ beq(T3, A1, &found);
1862 } 1943 }
1863 } 1944 }
1864 __ Bind(&next_iteration); 1945 __ Bind(&next_iteration);
1865 __ b(&loop); 1946 __ b(&loop);
1866 __ delay_slot()->addiu(T2, T2, 1947 __ delay_slot()->addiu(T2, T2,
1867 Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); 1948 Immediate(kWordSize * SubtypeTestCache::kTestEntryLength));
1868 // Fall through to not found. 1949 // Fall through to not found.
1869 __ Bind(&not_found); 1950 __ Bind(&not_found);
1870 __ Ret(); 1951 __ Ret();
1871 __ delay_slot()->mov(V0, NULLREG); 1952 __ delay_slot()->mov(V0, T7);
1872 1953
1873 __ Bind(&found); 1954 __ Bind(&found);
1874 __ Ret(); 1955 __ Ret();
1875 __ delay_slot()->lw(V0, 1956 __ delay_slot()->lw(V0,
1876 Address(T2, kWordSize * SubtypeTestCache::kTestResult)); 1957 Address(T2, kWordSize * SubtypeTestCache::kTestResult));
1877 } 1958 }
1878 1959
1879 1960
1880 // Used to check class and type arguments. Arguments passed in registers: 1961 // Used to check class and type arguments. Arguments passed in registers:
1881 // RA: return address. 1962 // RA: return address.
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1940 // Implements equality operator when one of the arguments is null 2021 // Implements equality operator when one of the arguments is null
1941 // (identity check) and updates ICData if necessary. 2022 // (identity check) and updates ICData if necessary.
1942 // RA: return address. 2023 // RA: return address.
1943 // A1: left argument. 2024 // A1: left argument.
1944 // A0: right argument. 2025 // A0: right argument.
1945 // T0: ICData. 2026 // T0: ICData.
1946 // V0: result. 2027 // V0: result.
1947 // TODO(srdjan): Move to VM stubs once Boolean objects become VM objects. 2028 // TODO(srdjan): Move to VM stubs once Boolean objects become VM objects.
1948 void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) { 2029 void StubCode::GenerateEqualityWithNullArgStub(Assembler* assembler) {
1949 __ TraceSimMsg("EqualityWithNullArgStub"); 2030 __ TraceSimMsg("EqualityWithNullArgStub");
2031 __ Comment("EqualityWithNullArgStub");
1950 __ EnterStubFrame(); 2032 __ EnterStubFrame();
1951 static const intptr_t kNumArgsTested = 2; 2033 static const intptr_t kNumArgsTested = 2;
1952 #if defined(DEBUG) 2034 #if defined(DEBUG)
1953 { Label ok; 2035 { Label ok;
1954 __ lw(TMP1, FieldAddress(T0, ICData::num_args_tested_offset())); 2036 __ lw(TMP1, FieldAddress(T0, ICData::num_args_tested_offset()));
1955 __ BranchEqual(TMP1, kNumArgsTested, &ok); 2037 __ BranchEqual(TMP1, kNumArgsTested, &ok);
1956 __ Stop("Incorrect ICData for equality"); 2038 __ Stop("Incorrect ICData for equality");
1957 __ Bind(&ok); 2039 __ Bind(&ok);
1958 } 2040 }
1959 #endif // DEBUG 2041 #endif // DEBUG
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
2041 2123
2042 // Calls to the runtime to optimize the given function. 2124 // Calls to the runtime to optimize the given function.
2043 // T0: function to be reoptimized. 2125 // T0: function to be reoptimized.
2044 // S4: argument descriptor (preserved). 2126 // S4: argument descriptor (preserved).
2045 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 2127 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
2046 __ TraceSimMsg("OptimizeFunctionStub"); 2128 __ TraceSimMsg("OptimizeFunctionStub");
2047 __ EnterStubFrame(); 2129 __ EnterStubFrame();
2048 __ addiu(SP, SP, Immediate(-3 * kWordSize)); 2130 __ addiu(SP, SP, Immediate(-3 * kWordSize));
2049 __ sw(S4, Address(SP, 2 * kWordSize)); 2131 __ sw(S4, Address(SP, 2 * kWordSize));
2050 // Setup space on stack for return value. 2132 // Setup space on stack for return value.
2051 __ sw(NULLREG, Address(SP, 1 * kWordSize)); 2133 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null()));
2134 __ sw(TMP, Address(SP, 1 * kWordSize));
2052 __ sw(T0, Address(SP, 0 * kWordSize)); 2135 __ sw(T0, Address(SP, 0 * kWordSize));
2053 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); 2136 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry);
2054 __ TraceSimMsg("OptimizeFunctionStub return"); 2137 __ TraceSimMsg("OptimizeFunctionStub return");
2055 __ lw(T0, Address(SP, 1 * kWordSize)); // Get Code object 2138 __ lw(T0, Address(SP, 1 * kWordSize)); // Get Code object
2056 __ lw(S4, Address(SP, 2 * kWordSize)); // Restore argument descriptor. 2139 __ lw(S4, Address(SP, 2 * kWordSize)); // Restore argument descriptor.
2057 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Discard argument. 2140 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Discard argument.
2058 2141
2059 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); 2142 __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
2060 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag); 2143 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag);
2061 __ LeaveStubFrameAndReturn(T0); 2144 __ LeaveStubFrameAndReturn(T0);
(...skipping 10 matching lines...) Expand all
2072 // Does identical check (object references are equal or not equal) with special 2155 // Does identical check (object references are equal or not equal) with special
2073 // checks for boxed numbers. 2156 // checks for boxed numbers.
2074 // RA: return address. 2157 // RA: return address.
2075 // SP + 4: left operand. 2158 // SP + 4: left operand.
2076 // SP + 0: right operand. 2159 // SP + 0: right operand.
2077 // Return: CMPRES is zero if equal, non-zero otherwise. 2160 // Return: CMPRES is zero if equal, non-zero otherwise.
2078 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint 2161 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
2079 // cannot contain a value that fits in Mint or Smi. 2162 // cannot contain a value that fits in Mint or Smi.
2080 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) { 2163 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) {
2081 __ TraceSimMsg("IdenticalWithNumberCheckStub"); 2164 __ TraceSimMsg("IdenticalWithNumberCheckStub");
2082 const Register ret = CMPRES; 2165 __ Comment("IdenticalWithNumberCheckStub");
2083 const Register temp1 = T2; 2166 const Register temp1 = T2;
2084 const Register temp2 = T3; 2167 const Register temp2 = T3;
2085 const Register left = T1; 2168 const Register left = T1;
2086 const Register right = T0; 2169 const Register right = T0;
2087 // Preserve left, right. 2170 // Preserve left, right.
2088 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 2171 __ addiu(SP, SP, Immediate(-4 * kWordSize));
2089 __ sw(T1, Address(SP, 1 * kWordSize)); 2172 __ sw(temp1, Address(SP, 3 * kWordSize));
2090 __ sw(T0, Address(SP, 0 * kWordSize)); 2173 __ sw(temp2, Address(SP, 2 * kWordSize));
2174 __ sw(left, Address(SP, 1 * kWordSize));
2175 __ sw(right, Address(SP, 0 * kWordSize));
2091 // TOS + 3: left argument. 2176 // TOS + 3: left argument.
2092 // TOS + 2: right argument. 2177 // TOS + 2: right argument.
2093 // TOS + 1: saved left 2178 // TOS + 1: saved left
2094 // TOS + 0: saved right 2179 // TOS + 0: saved right
2095 __ lw(left, Address(SP, 3 * kWordSize)); 2180 __ lw(left, Address(SP, 5 * kWordSize));
2096 __ lw(right, Address(SP, 2 * kWordSize)); 2181 __ lw(right, Address(SP, 4 * kWordSize));
2097 Label reference_compare, done, check_mint, check_bigint; 2182 Label reference_compare, done, check_mint, check_bigint;
2098 // If any of the arguments is Smi do reference compare. 2183 // If any of the arguments is Smi do reference compare.
2099 __ andi(temp1, left, Immediate(kSmiTagMask)); 2184 __ andi(temp1, left, Immediate(kSmiTagMask));
2100 __ beq(temp1, ZR, &reference_compare); 2185 __ beq(temp1, ZR, &reference_compare);
2101 __ andi(temp1, right, Immediate(kSmiTagMask)); 2186 __ andi(temp1, right, Immediate(kSmiTagMask));
2102 __ beq(temp1, ZR, &reference_compare); 2187 __ beq(temp1, ZR, &reference_compare);
2103 2188
2104 // Value compare for two doubles. 2189 // Value compare for two doubles.
2105 __ LoadImmediate(temp1, kDoubleCid); 2190 __ LoadImmediate(temp1, kDoubleCid);
2106 __ LoadClassId(temp2, left); 2191 __ LoadClassId(temp2, left);
2107 __ bne(temp1, temp2, &check_mint); 2192 __ bne(temp1, temp2, &check_mint);
2108 __ LoadClassId(temp2, right); 2193 __ LoadClassId(temp2, right);
2109 __ subu(ret, temp1, temp2); 2194 __ subu(CMPRES, temp1, temp2);
2110 __ bne(ret, ZR, &done); 2195 __ bne(CMPRES, ZR, &done);
2111 2196
2112 // Double values bitwise compare. 2197 // Double values bitwise compare.
2113 __ lw(temp1, FieldAddress(left, Double::value_offset() + 0 * kWordSize)); 2198 __ lw(temp1, FieldAddress(left, Double::value_offset() + 0 * kWordSize));
2114 __ lw(temp1, FieldAddress(right, Double::value_offset() + 0 * kWordSize)); 2199 __ lw(temp2, FieldAddress(right, Double::value_offset() + 0 * kWordSize));
2115 __ subu(ret, temp1, temp2); 2200 __ subu(CMPRES, temp1, temp2);
2116 __ bne(ret, ZR, &done); 2201 __ bne(CMPRES, ZR, &done);
2117 __ lw(temp1, FieldAddress(left, Double::value_offset() + 1 * kWordSize)); 2202 __ lw(temp1, FieldAddress(left, Double::value_offset() + 1 * kWordSize));
2118 __ lw(temp2, FieldAddress(right, Double::value_offset() + 1 * kWordSize)); 2203 __ lw(temp2, FieldAddress(right, Double::value_offset() + 1 * kWordSize));
2119 __ b(&done); 2204 __ b(&done);
2120 __ delay_slot()->subu(ret, temp1, temp2); 2205 __ delay_slot()->subu(CMPRES, temp1, temp2);
2121 2206
2122 __ Bind(&check_mint); 2207 __ Bind(&check_mint);
2123 __ LoadImmediate(temp1, kMintCid); 2208 __ LoadImmediate(temp1, kMintCid);
2124 __ LoadClassId(temp2, left); 2209 __ LoadClassId(temp2, left);
2125 __ bne(temp1, temp2, &check_bigint); 2210 __ bne(temp1, temp2, &check_bigint);
2126 __ LoadClassId(temp2, right); 2211 __ LoadClassId(temp2, right);
2127 __ subu(ret, temp1, temp2); 2212 __ subu(CMPRES, temp1, temp2);
2128 __ bne(ret, ZR, &done); 2213 __ bne(CMPRES, ZR, &done);
2129 2214
2130 __ lw(temp1, FieldAddress(left, Mint::value_offset() + 0 * kWordSize)); 2215 __ lw(temp1, FieldAddress(left, Mint::value_offset() + 0 * kWordSize));
2131 __ lw(temp2, FieldAddress(right, Mint::value_offset() + 0 * kWordSize)); 2216 __ lw(temp2, FieldAddress(right, Mint::value_offset() + 0 * kWordSize));
2132 __ subu(ret, temp1, temp2); 2217 __ subu(CMPRES, temp1, temp2);
2133 __ bne(ret, ZR, &done); 2218 __ bne(CMPRES, ZR, &done);
2134 __ lw(temp1, FieldAddress(left, Mint::value_offset() + 1 * kWordSize)); 2219 __ lw(temp1, FieldAddress(left, Mint::value_offset() + 1 * kWordSize));
2135 __ lw(temp2, FieldAddress(right, Mint::value_offset() + 1 * kWordSize)); 2220 __ lw(temp2, FieldAddress(right, Mint::value_offset() + 1 * kWordSize));
2136 __ b(&done); 2221 __ b(&done);
2137 __ delay_slot()->subu(ret, temp1, temp2); 2222 __ delay_slot()->subu(CMPRES, temp1, temp2);
2138 2223
2139 __ Bind(&check_bigint); 2224 __ Bind(&check_bigint);
2140 __ LoadImmediate(temp1, kBigintCid); 2225 __ LoadImmediate(temp1, kBigintCid);
2141 __ LoadClassId(temp2, left); 2226 __ LoadClassId(temp2, left);
2142 __ bne(temp1, temp2, &reference_compare); 2227 __ bne(temp1, temp2, &reference_compare);
2143 __ LoadClassId(temp2, right); 2228 __ LoadClassId(temp2, right);
2144 __ subu(ret, temp1, temp2); 2229 __ subu(CMPRES, temp1, temp2);
2145 __ bne(ret, ZR, &done); 2230 __ bne(CMPRES, ZR, &done);
2146 2231
2147 __ EnterStubFrame(0); 2232 __ EnterStubFrame();
2148 __ ReserveAlignedFrameSpace(2 * kWordSize); 2233 __ ReserveAlignedFrameSpace(2 * kWordSize);
2149 __ sw(T1, Address(SP, 1 * kWordSize)); 2234 __ sw(left, Address(SP, 1 * kWordSize));
2150 __ sw(T0, Address(SP, 0 * kWordSize)); 2235 __ sw(right, Address(SP, 0 * kWordSize));
2236 __ mov(A0, left);
2237 __ mov(A1, right);
2151 __ CallRuntime(kBigintCompareRuntimeEntry); 2238 __ CallRuntime(kBigintCompareRuntimeEntry);
2152 __ TraceSimMsg("IdenticalWithNumberCheckStub return"); 2239 __ TraceSimMsg("IdenticalWithNumberCheckStub return");
2153 // Result in V0, 0 means equal. 2240 // Result in V0, 0 means equal.
2154 __ LeaveStubFrame(); 2241 __ LeaveStubFrame();
2155 __ b(&done); 2242 __ b(&done);
2156 __ delay_slot()->mov(CMPRES, V0); 2243 __ delay_slot()->mov(CMPRES, V0);
2157 2244
2158 __ Bind(&reference_compare); 2245 __ Bind(&reference_compare);
2159 __ subu(ret, left, right); 2246 __ subu(CMPRES, left, right);
2160 __ Bind(&done); 2247 __ Bind(&done);
2161 // A branch or test after this comparison will check CMPRES == TMP1. 2248 // A branch or test after this comparison will check CMPRES == TMP1.
2162 __ mov(TMP1, ZR); 2249 __ mov(TMP1, ZR);
2163 __ lw(T0, Address(SP, 0 * kWordSize)); 2250 __ lw(right, Address(SP, 0 * kWordSize));
2164 __ lw(T1, Address(SP, 1 * kWordSize)); 2251 __ lw(left, Address(SP, 1 * kWordSize));
2252 __ lw(temp2, Address(SP, 2 * kWordSize));
2253 __ lw(temp1, Address(SP, 3 * kWordSize));
2165 __ Ret(); 2254 __ Ret();
2166 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); 2255 __ delay_slot()->addiu(SP, SP, Immediate(4 * kWordSize));
2167 } 2256 }
2168 2257
2169 } // namespace dart 2258 } // namespace dart
2170 2259
2171 #endif // defined TARGET_ARCH_MIPS 2260 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698