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

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

Issue 14854010: On MIPS, keeps Object::null() in a register. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « runtime/vm/stub_code_arm.cc ('k') | runtime/vm/stub_code_mips_test.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 #include "vm/globals.h" 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
87 // Retval is next to 1st argument. 87 // Retval is next to 1st argument.
88 __ delay_slot()->addiu(A3, A2, Immediate(kWordSize)); 88 __ delay_slot()->addiu(A3, A2, Immediate(kWordSize));
89 __ TraceSimMsg("CallToRuntimeStub return"); 89 __ TraceSimMsg("CallToRuntimeStub return");
90 90
91 // Reset exit frame information in Isolate structure. 91 // Reset exit frame information in Isolate structure.
92 __ sw(ZR, Address(CTX, Isolate::top_exit_frame_info_offset())); 92 __ sw(ZR, Address(CTX, Isolate::top_exit_frame_info_offset()));
93 93
94 // Load Context pointer from Isolate structure into A2. 94 // Load Context pointer from Isolate structure into A2.
95 __ lw(A2, Address(CTX, Isolate::top_context_offset())); 95 __ lw(A2, Address(CTX, Isolate::top_context_offset()));
96 96
97 // Reload NULLREG.
98 __ LoadImmediate(NULLREG, reinterpret_cast<intptr_t>(Object::null()));
99
97 // Reset Context pointer in Isolate structure. 100 // Reset Context pointer in Isolate structure.
98 __ LoadImmediate(A3, reinterpret_cast<intptr_t>(Object::null())); 101 __ sw(NULLREG, Address(CTX, Isolate::top_context_offset()));
99 __ sw(A3, Address(CTX, Isolate::top_context_offset()));
100 102
101 // Cache Context pointer into CTX while executing Dart code. 103 // Cache Context pointer into CTX while executing Dart code.
102 __ mov(CTX, A2); 104 __ mov(CTX, A2);
103 105
104 __ mov(SP, FP); 106 __ mov(SP, FP);
105 __ lw(RA, Address(SP, 1 * kWordSize)); 107 __ lw(RA, Address(SP, 1 * kWordSize));
106 __ lw(FP, Address(SP, 0 * kWordSize)); 108 __ lw(FP, Address(SP, 0 * kWordSize));
107 __ Ret(); 109 __ Ret();
108 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); 110 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize));
109 } 111 }
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 __ jalr(T5); 182 __ jalr(T5);
181 __ delay_slot()->mov(A0, SP); // Pass the pointer to the NativeArguments. 183 __ delay_slot()->mov(A0, SP); // Pass the pointer to the NativeArguments.
182 __ TraceSimMsg("CallNativeCFunctionStub return"); 184 __ TraceSimMsg("CallNativeCFunctionStub return");
183 185
184 // Reset exit frame information in Isolate structure. 186 // Reset exit frame information in Isolate structure.
185 __ sw(ZR, Address(CTX, Isolate::top_exit_frame_info_offset())); 187 __ sw(ZR, Address(CTX, Isolate::top_exit_frame_info_offset()));
186 188
187 // Load Context pointer from Isolate structure into A2. 189 // Load Context pointer from Isolate structure into A2.
188 __ lw(A2, Address(CTX, Isolate::top_context_offset())); 190 __ lw(A2, Address(CTX, Isolate::top_context_offset()));
189 191
192 // Reload NULLREG.
193 __ LoadImmediate(NULLREG, reinterpret_cast<intptr_t>(Object::null()));
194
190 // Reset Context pointer in Isolate structure. 195 // Reset Context pointer in Isolate structure.
191 __ LoadImmediate(A3, reinterpret_cast<intptr_t>(Object::null())); 196 __ sw(NULLREG, Address(CTX, Isolate::top_context_offset()));
192 __ sw(A3, Address(CTX, Isolate::top_context_offset()));
193 197
194 // Cache Context pointer into CTX while executing Dart code. 198 // Cache Context pointer into CTX while executing Dart code.
195 __ mov(CTX, A2); 199 __ mov(CTX, A2);
196 200
197 __ mov(SP, FP); 201 __ mov(SP, FP);
198 __ lw(RA, Address(SP, 1 * kWordSize)); 202 __ lw(RA, Address(SP, 1 * kWordSize));
199 __ lw(FP, Address(SP, 0 * kWordSize)); 203 __ lw(FP, Address(SP, 0 * kWordSize));
200 __ Ret(); 204 __ Ret();
201 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); 205 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize));
202 } 206 }
203 207
204 208
205 // Input parameters: 209 // Input parameters:
206 // S4: arguments descriptor array. 210 // S4: arguments descriptor array.
207 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) { 211 void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
208 __ TraceSimMsg("CallStaticFunctionStub"); 212 __ TraceSimMsg("CallStaticFunctionStub");
209 __ EnterStubFrame(); 213 __ EnterStubFrame();
210 // Setup space on stack for return value and preserve arguments descriptor. 214 // Setup space on stack for return value and preserve arguments descriptor.
211 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
212 215
213 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 216 __ addiu(SP, SP, Immediate(-2 * kWordSize));
214 __ sw(S4, Address(SP, 1 * kWordSize)); 217 __ sw(S4, Address(SP, 1 * kWordSize));
215 __ sw(T0, Address(SP, 0 * kWordSize)); 218 __ sw(NULLREG, Address(SP, 0 * kWordSize));
216 219
217 __ CallRuntime(kPatchStaticCallRuntimeEntry); 220 __ CallRuntime(kPatchStaticCallRuntimeEntry);
218 __ TraceSimMsg("CallStaticFunctionStub return"); 221 __ TraceSimMsg("CallStaticFunctionStub return");
219 222
220 // Get Code object result and restore arguments descriptor array. 223 // Get Code object result and restore arguments descriptor array.
221 __ lw(T0, Address(SP, 0 * kWordSize)); 224 __ lw(T0, Address(SP, 0 * kWordSize));
222 __ lw(S4, Address(SP, 1 * kWordSize)); 225 __ lw(S4, Address(SP, 1 * kWordSize));
223 __ addiu(SP, SP, Immediate(2 * kWordSize)); 226 __ addiu(SP, SP, Immediate(2 * kWordSize));
224 227
225 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); 228 __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
226 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag); 229 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag);
227 230
228 // Remove the stub frame as we are about to jump to the dart function. 231 // Remove the stub frame as we are about to jump to the dart function.
229 __ LeaveStubFrameAndReturn(T0); 232 __ LeaveStubFrameAndReturn(T0);
230 } 233 }
231 234
232 235
233 // Called from a static call only when an invalid code has been entered 236 // Called from a static call only when an invalid code has been entered
234 // (invalid because its function was optimized or deoptimized). 237 // (invalid because its function was optimized or deoptimized).
235 // S4: arguments descriptor array. 238 // S4: arguments descriptor array.
236 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) { 239 void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
237 // Create a stub frame as we are pushing some objects on the stack before 240 // Create a stub frame as we are pushing some objects on the stack before
238 // calling into the runtime. 241 // calling into the runtime.
239 __ EnterStubFrame(); 242 __ EnterStubFrame();
240 // Setup space on stack for return value and preserve arguments descriptor. 243 // Setup space on stack for return value and preserve arguments descriptor.
241 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
242 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 244 __ addiu(SP, SP, Immediate(-2 * kWordSize));
243 __ sw(S4, Address(SP, 1 * kWordSize)); 245 __ sw(S4, Address(SP, 1 * kWordSize));
244 __ sw(T0, Address(SP, 0 * kWordSize)); 246 __ sw(NULLREG, Address(SP, 0 * kWordSize));
245 __ CallRuntime(kFixCallersTargetRuntimeEntry); 247 __ CallRuntime(kFixCallersTargetRuntimeEntry);
246 // Get Code object result and restore arguments descriptor array. 248 // Get Code object result and restore arguments descriptor array.
247 __ lw(T0, Address(SP, 0 * kWordSize)); 249 __ lw(T0, Address(SP, 0 * kWordSize));
248 __ lw(S4, Address(SP, 1 * kWordSize)); 250 __ lw(S4, Address(SP, 1 * kWordSize));
249 __ addiu(SP, SP, Immediate(2 * kWordSize)); 251 __ addiu(SP, SP, Immediate(2 * kWordSize));
250 252
251 // Jump to the dart function. 253 // Jump to the dart function.
252 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); 254 __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
253 __ AddImmediate(T0, T0, Instructions::HeaderSize() - kHeapObjectTag); 255 __ AddImmediate(T0, T0, Instructions::HeaderSize() - kHeapObjectTag);
254 256
255 // Remove the stub frame. 257 // Remove the stub frame.
256 __ LeaveStubFrameAndReturn(T0); 258 __ LeaveStubFrameAndReturn(T0);
257 } 259 }
258 260
259 261
260 // Input parameters: 262 // Input parameters:
261 // A1: Smi-tagged argument count, may be zero. 263 // A1: Smi-tagged argument count, may be zero.
262 // FP[kLastParamSlotIndex]: Last argument. 264 // FP[kLastParamSlotIndex]: Last argument.
263 static void PushArgumentsArray(Assembler* assembler) { 265 static void PushArgumentsArray(Assembler* assembler) {
264 __ TraceSimMsg("PushArgumentsArray"); 266 __ TraceSimMsg("PushArgumentsArray");
265 // Allocate array to store arguments of caller. 267 // Allocate array to store arguments of caller.
266 __ LoadImmediate(A0, reinterpret_cast<intptr_t>(Object::null())); 268 __ mov(A0, NULLREG);
267 // A0: Null element type for raw Array. 269 // A0: Null element type for raw Array.
268 // A1: Smi-tagged argument count, may be zero. 270 // A1: Smi-tagged argument count, may be zero.
269 __ BranchLink(&StubCode::AllocateArrayLabel()); 271 __ BranchLink(&StubCode::AllocateArrayLabel());
270 __ TraceSimMsg("PushArgumentsArray return"); 272 __ TraceSimMsg("PushArgumentsArray return");
271 // V0: newly allocated array. 273 // V0: newly allocated array.
272 // A1: Smi-tagged argument count, may be zero (was preserved by the stub). 274 // A1: Smi-tagged argument count, may be zero (was preserved by the stub).
273 __ Push(V0); // Array is in V0 and on top of stack. 275 __ Push(V0); // Array is in V0 and on top of stack.
274 __ sll(T1, A1, 1); 276 __ sll(T1, A1, 1);
275 __ addu(T1, FP, T1); 277 __ addu(T1, FP, T1);
276 __ AddImmediate(T1, (kLastParamSlotIndex - 1) * kWordSize); 278 __ AddImmediate(T1, (kLastParamSlotIndex - 1) * kWordSize);
(...skipping 28 matching lines...) Expand all
305 // Load the receiver. 307 // Load the receiver.
306 __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 308 __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
307 __ sll(TMP1, A1, 1); // A1 is Smi. 309 __ sll(TMP1, A1, 1); // A1 is Smi.
308 __ addu(TMP1, FP, TMP1); 310 __ addu(TMP1, FP, TMP1);
309 __ lw(T1, Address(TMP1, (kLastParamSlotIndex - 1) * kWordSize)); 311 __ lw(T1, Address(TMP1, (kLastParamSlotIndex - 1) * kWordSize));
310 312
311 // Push space for the return value. 313 // Push space for the return value.
312 // Push the receiver. 314 // Push the receiver.
313 // Push TMP1 data object. 315 // Push TMP1 data object.
314 // Push arguments descriptor array. 316 // Push arguments descriptor array.
315 __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null()));
316 __ addiu(SP, SP, Immediate(-4 * kWordSize)); 317 __ addiu(SP, SP, Immediate(-4 * kWordSize));
317 __ sw(TMP1, Address(SP, 3 * kWordSize)); 318 __ sw(NULLREG, Address(SP, 3 * kWordSize));
318 __ sw(T1, Address(SP, 2 * kWordSize)); 319 __ sw(T1, Address(SP, 2 * kWordSize));
319 __ sw(S5, Address(SP, 1 * kWordSize)); 320 __ sw(S5, Address(SP, 1 * kWordSize));
320 __ sw(S4, Address(SP, 0 * kWordSize)); 321 __ sw(S4, Address(SP, 0 * kWordSize));
321 322
322 // A1: Smi-tagged arguments array length. 323 // A1: Smi-tagged arguments array length.
323 PushArgumentsArray(assembler); 324 PushArgumentsArray(assembler);
324 __ TraceSimMsg("InstanceFunctionLookupStub return"); 325 __ TraceSimMsg("InstanceFunctionLookupStub return");
325 326
326 // Stack: 327 // Stack:
327 // TOS + 0: argument array. 328 // TOS + 0: argument array.
(...skipping 221 matching lines...) Expand 10 before | Expand all | Expand 10 after
549 FieldAddress(V0, Array::length_offset()), 550 FieldAddress(V0, Array::length_offset()),
550 A1); 551 A1);
551 552
552 // Calculate the size tag. 553 // Calculate the size tag.
553 // V0: new object start as a tagged pointer. 554 // V0: new object start as a tagged pointer.
554 // A1: Array length as Smi. 555 // A1: Array length as Smi.
555 // T2: new object end address. 556 // T2: new object end address.
556 // T3: array size. 557 // T3: array size.
557 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; 558 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2;
558 // If no size tag overflow, shift T3 left, else set T3 to zero. 559 // If no size tag overflow, shift T3 left, else set T3 to zero.
559 __ LoadImmediate(TMP2, RawObject::SizeTag::kMaxSizeTag); 560 __ LoadImmediate(T4, RawObject::SizeTag::kMaxSizeTag);
560 __ sltu(CMPRES, TMP2, T3); // CMPRES = TMP2 < T3 ? 1 : 0 561 __ sltu(CMPRES, T4, T3); // CMPRES = T4 < T3 ? 1 : 0
561 __ sll(TMP1, T3, shift); // TMP1 = T3 << shift; 562 __ sll(TMP1, T3, shift); // TMP1 = T3 << shift;
562 __ movz(T3, TMP1, CMPRES); // T3 = TMP2 >= T3 ? 0 : T3 563 __ movz(T3, TMP1, CMPRES); // T3 = T4 >= T3 ? 0 : T3
563 __ movn(T3, ZR, CMPRES); // T3 = TMP2 < T3 ? TMP1 : T3 564 __ movn(T3, ZR, CMPRES); // T3 = T4 < T3 ? TMP1 : T3
564 565
565 // Get the class index and insert it into the tags. 566 // Get the class index and insert it into the tags.
566 __ LoadImmediate(TMP1, RawObject::ClassIdTag::encode(kArrayCid)); 567 __ LoadImmediate(TMP1, RawObject::ClassIdTag::encode(kArrayCid));
567 __ or_(T3, T3, TMP1); 568 __ or_(T3, T3, TMP1);
568 __ sw(T3, FieldAddress(V0, Array::tags_offset())); 569 __ sw(T3, FieldAddress(V0, Array::tags_offset()));
569 570
570 // Initialize all array elements to raw_null. 571 // Initialize all array elements to raw_null.
571 // V0: new object start as a tagged pointer. 572 // V0: new object start as a tagged pointer.
572 // T2: new object end address. 573 // T2: new object end address.
573 // A1: Array length as Smi. 574 // A1: Array length as Smi.
574 __ AddImmediate(T3, V0, Array::data_offset() - kHeapObjectTag); 575 __ AddImmediate(T3, V0, Array::data_offset() - kHeapObjectTag);
575 // T3: iterator which initially points to the start of the variable 576 // T3: iterator which initially points to the start of the variable
576 // data area to be initialized. 577 // data area to be initialized.
577 578
578 Label loop, loop_exit; 579 Label loop, loop_exit;
579 intptr_t null = reinterpret_cast<intptr_t>(Object::null());
580 uint16_t null_lo = Utils::Low16Bits(null);
581 uint16_t null_hi = Utils::High16Bits(null);
582 __ lui(TMP1, Immediate(null_hi));
583 __ BranchUnsignedGreaterEqual(T3, T2, &loop_exit); 580 __ BranchUnsignedGreaterEqual(T3, T2, &loop_exit);
584 __ delay_slot()->ori(TMP1, TMP1, Immediate(null_lo));
585 __ Bind(&loop); 581 __ Bind(&loop);
586 __ addiu(T3, T3, Immediate(kWordSize)); 582 __ addiu(T3, T3, Immediate(kWordSize));
587 __ bne(T3, T2, &loop); 583 __ bne(T3, T2, &loop);
588 __ delay_slot()->sw(TMP1, Address(T3, -kWordSize)); 584 __ delay_slot()->sw(NULLREG, Address(T3, -kWordSize));
589 __ Bind(&loop_exit); 585 __ Bind(&loop_exit);
590 586
591 // Done allocating and initializing the array. 587 // Done allocating and initializing the array.
592 // V0: new object. 588 // V0: new object.
593 // A1: Array length as Smi (preserved for the caller.) 589 // A1: Array length as Smi (preserved for the caller.)
594 __ Ret(); 590 __ Ret();
595 } 591 }
596 592
597 // Unable to allocate the array using the fast inline code, just call 593 // Unable to allocate the array using the fast inline code, just call
598 // into the runtime. 594 // into the runtime.
599 __ Bind(&slow_case); 595 __ Bind(&slow_case);
600 // Create a stub frame as we are pushing some objects on the stack before 596 // Create a stub frame as we are pushing some objects on the stack before
601 // calling into the runtime. 597 // calling into the runtime.
602 __ EnterStubFrame(); 598 __ EnterStubFrame();
603 __ LoadImmediate(TMP1, reinterpret_cast<intptr_t>(Object::null()));
604 // Setup space on stack for return value. 599 // Setup space on stack for return value.
605 // Push array length as Smi and element type. 600 // Push array length as Smi and element type.
606 __ addiu(SP, SP, Immediate(-3 * kWordSize)); 601 __ addiu(SP, SP, Immediate(-3 * kWordSize));
607 __ sw(TMP1, Address(SP, 2 * kWordSize)); 602 __ sw(NULLREG, Address(SP, 2 * kWordSize));
608 __ sw(A1, Address(SP, 1 * kWordSize)); 603 __ sw(A1, Address(SP, 1 * kWordSize));
609 __ sw(T3, Address(SP, 0 * kWordSize)); 604 __ sw(T3, Address(SP, 0 * kWordSize));
610 __ CallRuntime(kAllocateArrayRuntimeEntry); 605 __ CallRuntime(kAllocateArrayRuntimeEntry);
611 __ TraceSimMsg("AllocateArrayStub return"); 606 __ TraceSimMsg("AllocateArrayStub return");
612 // Pop arguments; result is popped in IP. 607 // Pop arguments; result is popped in IP.
613 __ lw(TMP1, Address(SP, 2 * kWordSize)); 608 __ lw(TMP1, Address(SP, 2 * kWordSize));
614 __ lw(A1, Address(SP, 1 * kWordSize)); 609 __ lw(A1, Address(SP, 1 * kWordSize));
615 __ lw(T3, Address(SP, 0 * kWordSize)); 610 __ lw(T3, Address(SP, 0 * kWordSize));
616 __ addiu(SP, SP, Immediate(3 * kWordSize)); 611 __ addiu(SP, SP, Immediate(3 * kWordSize));
617 __ mov(V0, TMP1); 612 __ mov(V0, TMP1);
(...skipping 18 matching lines...) Expand all
636 __ subu(T0, T0, TMP1); 631 __ subu(T0, T0, TMP1);
637 632
638 // Load closure object in T1. 633 // Load closure object in T1.
639 __ sll(T1, T0, 1); // T0 (num_args - 1) is a Smi. 634 __ sll(T1, T0, 1); // T0 (num_args - 1) is a Smi.
640 __ addu(T1, SP, T1); 635 __ addu(T1, SP, T1);
641 __ lw(T1, Address(T1)); 636 __ lw(T1, Address(T1));
642 637
643 // Verify that T1 is a closure by checking its class. 638 // Verify that T1 is a closure by checking its class.
644 Label not_closure; 639 Label not_closure;
645 640
646 __ LoadImmediate(T7, reinterpret_cast<intptr_t>(Object::null()));
647 // See if it is not a closure, but null object. 641 // See if it is not a closure, but null object.
648 __ beq(T1, T7, &not_closure); 642 __ beq(T1, NULLREG, &not_closure);
649 643
650 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); 644 __ andi(CMPRES, T1, Immediate(kSmiTagMask));
651 __ beq(CMPRES, ZR, &not_closure); // Not a closure, but a smi. 645 __ beq(CMPRES, ZR, &not_closure); // Not a closure, but a smi.
652 646
653 // Verify that the class of the object is a closure class by checking that 647 // Verify that the class of the object is a closure class by checking that
654 // class.signature_function() is not null. 648 // class.signature_function() is not null.
655 __ LoadClass(T0, T1); 649 __ LoadClass(T0, T1);
656 __ lw(T0, FieldAddress(T0, Class::signature_function_offset())); 650 __ lw(T0, FieldAddress(T0, Class::signature_function_offset()));
657 651
658 // See if actual class is not a closure class. 652 // See if actual class is not a closure class.
659 __ beq(T0, T7, &not_closure); 653 __ beq(T0, NULLREG, &not_closure);
660 654
661 // T0 is just the signature function. Load the actual closure function. 655 // T0 is just the signature function. Load the actual closure function.
662 __ lw(T2, FieldAddress(T1, Closure::function_offset())); 656 __ lw(T2, FieldAddress(T1, Closure::function_offset()));
663 657
664 // Load closure context in CTX; note that CTX has already been preserved. 658 // Load closure context in CTX; note that CTX has already been preserved.
665 __ lw(CTX, FieldAddress(T1, Closure::context_offset())); 659 __ lw(CTX, FieldAddress(T1, Closure::context_offset()));
666 660
667 Label function_compiled; 661 Label function_compiled;
668 // Load closure function code in T0. 662 // Load closure function code in T0.
669 __ lw(T0, FieldAddress(T2, Function::code_offset())); 663 __ lw(T0, FieldAddress(T2, Function::code_offset()));
670 __ bne(T0, T7, &function_compiled); 664 __ bne(T0, NULLREG, &function_compiled);
671 665
672 // Create a stub frame as we are pushing some objects on the stack before 666 // Create a stub frame as we are pushing some objects on the stack before
673 // calling into the runtime. 667 // calling into the runtime.
674 __ EnterStubFrame(); 668 __ EnterStubFrame();
675 669
676 // Preserve arguments descriptor array and read-only function object argument. 670 // Preserve arguments descriptor array and read-only function object argument.
677 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 671 __ addiu(SP, SP, Immediate(-2 * kWordSize));
678 __ sw(S4, Address(SP, 1 * kWordSize)); 672 __ sw(S4, Address(SP, 1 * kWordSize));
679 __ sw(T2, Address(SP, 0 * kWordSize)); 673 __ sw(T2, Address(SP, 0 * kWordSize));
680 __ CallRuntime(kCompileFunctionRuntimeEntry); 674 __ CallRuntime(kCompileFunctionRuntimeEntry);
(...skipping 22 matching lines...) Expand all
703 // If no call method exists, throw a NoSuchMethodError. 697 // If no call method exists, throw a NoSuchMethodError.
704 // T1: non-closure object. 698 // T1: non-closure object.
705 // S4: arguments descriptor array. 699 // S4: arguments descriptor array.
706 700
707 // Create a stub frame as we are pushing some objects on the stack before 701 // Create a stub frame as we are pushing some objects on the stack before
708 // calling into the runtime. 702 // calling into the runtime.
709 __ EnterStubFrame(); 703 __ EnterStubFrame();
710 704
711 // Setup space on stack for result from error reporting. 705 // Setup space on stack for result from error reporting.
712 __ addiu(SP, SP, Immediate(2 * kWordSize)); 706 __ addiu(SP, SP, Immediate(2 * kWordSize));
713 __ sw(T7, Address(SP, 1 * kWordSize)); // Arguments descriptor and raw null. 707 // Arguments descriptor and raw null.
708 __ sw(NULLREG, Address(SP, 1 * kWordSize));
714 __ sw(S4, Address(SP, 0 * kWordSize)); 709 __ sw(S4, Address(SP, 0 * kWordSize));
715 710
716 // Load smi-tagged arguments array length, including the non-closure. 711 // Load smi-tagged arguments array length, including the non-closure.
717 __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 712 __ lw(A1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
718 PushArgumentsArray(assembler); 713 PushArgumentsArray(assembler);
719 714
720 // Stack: 715 // Stack:
721 // TOS + 0: Argument array. 716 // TOS + 0: Argument array.
722 // TOS + 1: Arguments descriptor array. 717 // TOS + 1: Arguments descriptor array.
723 // TOS + 2: Place for result from the call. 718 // TOS + 2: Place for result from the call.
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
794 // Load arguments descriptor array into S4, which is passed to Dart code. 789 // Load arguments descriptor array into S4, which is passed to Dart code.
795 __ lw(S4, Address(A1, VMHandles::kOffsetOfRawPtrInHandle)); 790 __ lw(S4, Address(A1, VMHandles::kOffsetOfRawPtrInHandle));
796 791
797 // Load number of arguments into S5. 792 // Load number of arguments into S5.
798 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 793 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
799 __ SmiUntag(T1); 794 __ SmiUntag(T1);
800 795
801 // Compute address of 'arguments array' data area into A2. 796 // Compute address of 'arguments array' data area into A2.
802 __ lw(A2, Address(A2, VMHandles::kOffsetOfRawPtrInHandle)); 797 __ lw(A2, Address(A2, VMHandles::kOffsetOfRawPtrInHandle));
803 798
799 // Load the null Object into NULLREG for easy comparisons.
800 __ LoadImmediate(NULLREG, reinterpret_cast<intptr_t>(Object::null()));
801
804 // Set up arguments for the Dart call. 802 // Set up arguments for the Dart call.
805 Label push_arguments; 803 Label push_arguments;
806 Label done_push_arguments; 804 Label done_push_arguments;
807 __ beq(T1, ZR, &done_push_arguments); // check if there are arguments. 805 __ beq(T1, ZR, &done_push_arguments); // check if there are arguments.
808 __ delay_slot()->addiu(A2, A2, 806 __ delay_slot()->addiu(A2, A2,
809 Immediate(Array::data_offset() - kHeapObjectTag)); 807 Immediate(Array::data_offset() - kHeapObjectTag));
810 __ mov(A1, ZR); 808 __ mov(A1, ZR);
811 __ Bind(&push_arguments); 809 __ Bind(&push_arguments);
812 __ lw(A3, Address(A2)); 810 __ lw(A3, Address(A2));
813 __ Push(A3); 811 __ Push(A3);
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
903 __ addiu(V0, V0, Immediate(kHeapObjectTag)); 901 __ addiu(V0, V0, Immediate(kHeapObjectTag));
904 902
905 // Calculate the size tag. 903 // Calculate the size tag.
906 // V0: new object. 904 // V0: new object.
907 // T1: number of context variables. 905 // T1: number of context variables.
908 // T2: object size. 906 // T2: object size.
909 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2; 907 const intptr_t shift = RawObject::kSizeTagBit - kObjectAlignmentLog2;
910 __ LoadImmediate(TMP1, RawObject::SizeTag::kMaxSizeTag); 908 __ LoadImmediate(TMP1, RawObject::SizeTag::kMaxSizeTag);
911 __ sltu(CMPRES, TMP1, T2); // CMPRES = T2 > TMP1 ? 1 : 0. 909 __ sltu(CMPRES, TMP1, T2); // CMPRES = T2 > TMP1 ? 1 : 0.
912 __ movn(T2, ZR, CMPRES); // T2 = CMPRES != 0 ? 0 : T2. 910 __ movn(T2, ZR, CMPRES); // T2 = CMPRES != 0 ? 0 : T2.
913 __ sll(TMP1, T2, shift); // TMP2 = T2 << shift. 911 __ sll(TMP1, T2, shift); // TMP1 = T2 << shift.
914 __ movz(T2, TMP1, CMPRES); // T2 = CMPRES == 0 ? TMP1 : T2. 912 __ movz(T2, TMP1, CMPRES); // T2 = CMPRES == 0 ? TMP1 : T2.
915 913
916 // Get the class index and insert it into the tags. 914 // Get the class index and insert it into the tags.
917 // T2: size and bit tags. 915 // T2: size and bit tags.
918 __ LoadImmediate(TMP1, RawObject::ClassIdTag::encode(context_class.id())); 916 __ LoadImmediate(TMP1, RawObject::ClassIdTag::encode(context_class.id()));
919 __ or_(T2, T2, TMP1); 917 __ or_(T2, T2, TMP1);
920 __ sw(T2, FieldAddress(V0, Context::tags_offset())); 918 __ sw(T2, FieldAddress(V0, Context::tags_offset()));
921 919
922 // Setup up number of context variables field. 920 // Setup up number of context variables field.
923 // V0: new object. 921 // V0: new object.
924 // T1: number of context variables as integer value (not object). 922 // T1: number of context variables as integer value (not object).
925 __ sw(T1, FieldAddress(V0, Context::num_variables_offset())); 923 __ sw(T1, FieldAddress(V0, Context::num_variables_offset()));
926 924
927 // Setup isolate field. 925 // Setup isolate field.
928 // Load Isolate pointer from Context structure into R2. 926 // Load Isolate pointer from Context structure into R2.
929 // V0: new object. 927 // V0: new object.
930 // T1: number of context variables. 928 // T1: number of context variables.
931 __ lw(T2, FieldAddress(CTX, Context::isolate_offset())); 929 __ lw(T2, FieldAddress(CTX, Context::isolate_offset()));
932 // T2: isolate, not an object. 930 // T2: isolate, not an object.
933 __ sw(T2, FieldAddress(V0, Context::isolate_offset())); 931 __ sw(T2, FieldAddress(V0, Context::isolate_offset()));
934 932
935 __ LoadImmediate(T2, reinterpret_cast<intptr_t>(Object::null()));
936
937 // Initialize the context variables. 933 // Initialize the context variables.
938 // V0: new object. 934 // V0: new object.
939 // T1: number of context variables. 935 // T1: number of context variables.
940 // T2: raw null.
941 Label loop, loop_exit; 936 Label loop, loop_exit;
942 __ blez(T1, &loop_exit); 937 __ blez(T1, &loop_exit);
943 // Setup the parent field. 938 // Setup the parent field.
944 __ delay_slot()->sw(T2, FieldAddress(V0, Context::parent_offset())); 939 __ delay_slot()->sw(NULLREG, FieldAddress(V0, Context::parent_offset()));
945 __ AddImmediate(T3, V0, Context::variable_offset(0) - kHeapObjectTag); 940 __ AddImmediate(T3, V0, Context::variable_offset(0) - kHeapObjectTag);
946 __ sll(T1, T1, 2); 941 __ sll(T1, T1, 2);
947 __ Bind(&loop); 942 __ Bind(&loop);
948 __ addiu(T1, T1, Immediate(-kWordSize)); 943 __ addiu(T1, T1, Immediate(-kWordSize));
949 __ addu(TMP1, T3, T1); 944 __ addu(TMP1, T3, T1);
950 __ bgtz(T1, &loop); 945 __ bgtz(T1, &loop);
951 __ delay_slot()->sw(T2, Address(TMP1)); 946 __ delay_slot()->sw(NULLREG, Address(TMP1));
952 __ Bind(&loop_exit); 947 __ Bind(&loop_exit);
953 948
954 // Done allocating and initializing the context. 949 // Done allocating and initializing the context.
955 // V0: new object. 950 // V0: new object.
956 __ Ret(); 951 __ Ret();
957 952
958 __ Bind(&slow_case); 953 __ Bind(&slow_case);
959 } 954 }
960 // Create a stub frame as we are pushing some objects on the stack before 955 // Create a stub frame as we are pushing some objects on the stack before
961 // calling into the runtime. 956 // calling into the runtime.
962 __ EnterStubFrame(); 957 __ EnterStubFrame();
963 // Setup space on stack for return value. 958 // Setup space on stack for return value.
964 __ LoadImmediate(T2, reinterpret_cast<intptr_t>(Object::null()));
965 __ SmiTag(T1); 959 __ SmiTag(T1);
966 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 960 __ addiu(SP, SP, Immediate(-2 * kWordSize));
967 __ sw(T2, Address(SP, 1 * kWordSize)); 961 __ sw(NULLREG, Address(SP, 1 * kWordSize));
968 __ sw(T1, Address(SP, 0 * kWordSize)); 962 __ sw(T1, Address(SP, 0 * kWordSize));
969 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context. 963 __ CallRuntime(kAllocateContextRuntimeEntry); // Allocate context.
970 __ lw(V0, Address(SP, 1 * kWordSize)); // Get the new context. 964 __ lw(V0, Address(SP, 1 * kWordSize)); // Get the new context.
971 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Pop argument and return. 965 __ addiu(SP, SP, Immediate(2 * kWordSize)); // Pop argument and return.
972 966
973 // V0: new object 967 // V0: new object
974 // Restore the frame pointer. 968 // Restore the frame pointer.
975 __ LeaveStubFrameAndReturn(); 969 __ LeaveStubFrameAndReturn();
976 } 970 }
977 971
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
1124 // T1: new object type arguments (if is_cls_parameterized). 1118 // T1: new object type arguments (if is_cls_parameterized).
1125 // Set the tags. 1119 // Set the tags.
1126 uword tags = 0; 1120 uword tags = 0;
1127 tags = RawObject::SizeTag::update(instance_size, tags); 1121 tags = RawObject::SizeTag::update(instance_size, tags);
1128 ASSERT(cls.id() != kIllegalCid); 1122 ASSERT(cls.id() != kIllegalCid);
1129 tags = RawObject::ClassIdTag::update(cls.id(), tags); 1123 tags = RawObject::ClassIdTag::update(cls.id(), tags);
1130 __ LoadImmediate(T0, tags); 1124 __ LoadImmediate(T0, tags);
1131 __ sw(T0, Address(T2, Instance::tags_offset())); 1125 __ sw(T0, Address(T2, Instance::tags_offset()));
1132 1126
1133 // Initialize the remaining words of the object. 1127 // Initialize the remaining words of the object.
1134 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
1135
1136 // T0: raw null.
1137 // T2: new object start. 1128 // T2: new object start.
1138 // T3: next object start. 1129 // T3: next object start.
1139 // T1: new object type arguments (if is_cls_parameterized). 1130 // T1: new object type arguments (if is_cls_parameterized).
1140 // First try inlining the initialization without a loop. 1131 // First try inlining the initialization without a loop.
1141 if (instance_size < (kInlineInstanceSize * kWordSize)) { 1132 if (instance_size < (kInlineInstanceSize * kWordSize)) {
1142 // Check if the object contains any non-header fields. 1133 // Check if the object contains any non-header fields.
1143 // Small objects are initialized using a consecutive set of writes. 1134 // Small objects are initialized using a consecutive set of writes.
1144 for (intptr_t current_offset = sizeof(RawObject); 1135 for (intptr_t current_offset = sizeof(RawObject);
1145 current_offset < instance_size; 1136 current_offset < instance_size;
1146 current_offset += kWordSize) { 1137 current_offset += kWordSize) {
1147 __ sw(T0, Address(T2, current_offset)); 1138 __ sw(NULLREG, Address(T2, current_offset));
1148 } 1139 }
1149 } else { 1140 } else {
1150 __ addiu(T4, T2, Immediate(sizeof(RawObject))); 1141 __ addiu(T4, T2, Immediate(sizeof(RawObject)));
1151 // Loop until the whole object is initialized. 1142 // Loop until the whole object is initialized.
1152 // T0: raw null.
1153 // T2: new object. 1143 // T2: new object.
1154 // T3: next object start. 1144 // T3: next object start.
1155 // T4: next word to be initialized. 1145 // T4: next word to be initialized.
1156 // T1: new object type arguments (if is_cls_parameterized). 1146 // T1: new object type arguments (if is_cls_parameterized).
1157 Label loop, loop_exit; 1147 Label loop, loop_exit;
1158 __ BranchUnsignedGreaterEqual(T4, T3, &loop_exit); 1148 __ BranchUnsignedGreaterEqual(T4, T3, &loop_exit);
1159 __ Bind(&loop); 1149 __ Bind(&loop);
1160 __ addiu(T4, T4, Immediate(kWordSize)); 1150 __ addiu(T4, T4, Immediate(kWordSize));
1161 __ bne(T4, T3, &loop); 1151 __ bne(T4, T3, &loop);
1162 __ delay_slot()->sw(T0, Address(T4, -kWordSize)); 1152 __ delay_slot()->sw(NULLREG, Address(T4, -kWordSize));
1163 __ Bind(&loop_exit); 1153 __ Bind(&loop_exit);
1164 } 1154 }
1165 if (is_cls_parameterized) { 1155 if (is_cls_parameterized) {
1166 // R1: new object type arguments. 1156 // R1: new object type arguments.
1167 // Set the type arguments in the new object. 1157 // Set the type arguments in the new object.
1168 __ sw(T1, Address(T2, cls.type_arguments_field_offset())); 1158 __ sw(T1, Address(T2, cls.type_arguments_field_offset()));
1169 } 1159 }
1170 // Done allocating and initializing the instance. 1160 // Done allocating and initializing the instance.
1171 // T2: new object still missing its heap tag. 1161 // T2: new object still missing its heap tag.
1172 __ Ret(); 1162 __ Ret();
1173 __ delay_slot()->addiu(V0, T2, Immediate(kHeapObjectTag)); 1163 __ delay_slot()->addiu(V0, T2, Immediate(kHeapObjectTag));
1174 1164
1175 __ Bind(&slow_case); 1165 __ Bind(&slow_case);
1176 } 1166 }
1177 if (is_cls_parameterized) { 1167 if (is_cls_parameterized) {
1178 __ lw(T1, Address(SP, 1 * kWordSize)); 1168 __ lw(T1, Address(SP, 1 * kWordSize));
1179 __ lw(T0, Address(SP, 0 * kWordSize)); 1169 __ lw(T0, Address(SP, 0 * kWordSize));
1180 } 1170 }
1181 // Create a stub frame as we are pushing some objects on the stack before 1171 // Create a stub frame as we are pushing some objects on the stack before
1182 // calling into the runtime. 1172 // calling into the runtime.
1183 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime. 1173 __ EnterStubFrame(true); // Uses pool pointer to pass cls to runtime.
1184 __ LoadImmediate(T2, reinterpret_cast<intptr_t>(Object::null()));
1185 __ LoadObject(TMP1, cls); 1174 __ LoadObject(TMP1, cls);
1186 1175
1187 __ addiu(SP, SP, Immediate(-4 * kWordSize)); 1176 __ addiu(SP, SP, Immediate(-4 * kWordSize));
1188 __ sw(T2, Address(SP, 3 * kWordSize)); // Space on stack for return value. 1177 // Space on stack for return value.
1178 __ sw(NULLREG, Address(SP, 3 * kWordSize));
1189 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Class of object to be allocated. 1179 __ sw(TMP1, Address(SP, 2 * kWordSize)); // Class of object to be allocated.
1190 1180
1191 if (is_cls_parameterized) { 1181 if (is_cls_parameterized) {
1192 // Push type arguments of object to be allocated and of instantiator. 1182 // Push type arguments of object to be allocated and of instantiator.
1193 __ sw(T1, Address(SP, 1 * kWordSize)); 1183 __ sw(T1, Address(SP, 1 * kWordSize));
1194 __ sw(T0, Address(SP, 0 * kWordSize)); 1184 __ sw(T0, Address(SP, 0 * kWordSize));
1195 } else { 1185 } else {
1196 // Push null type arguments and kNoInstantiator. 1186 // Push null type arguments and kNoInstantiator.
1197 __ LoadImmediate(T1, Smi::RawValue(StubCode::kNoInstantiator)); 1187 __ LoadImmediate(T1, Smi::RawValue(StubCode::kNoInstantiator));
1198 __ sw(T2, Address(SP, 1 * kWordSize)); 1188 __ sw(NULLREG, Address(SP, 1 * kWordSize));
1199 __ sw(T1, Address(SP, 0 * kWordSize)); 1189 __ sw(T1, Address(SP, 0 * kWordSize));
1200 } 1190 }
1201 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object. 1191 __ CallRuntime(kAllocateObjectRuntimeEntry); // Allocate object.
1202 __ TraceSimMsg("AllocationStubForClass return"); 1192 __ TraceSimMsg("AllocationStubForClass return");
1203 // Pop result (newly allocated object). 1193 // Pop result (newly allocated object).
1204 __ lw(V0, Address(SP, 3 * kWordSize)); 1194 __ lw(V0, Address(SP, 3 * kWordSize));
1205 __ addiu(SP, SP, Immediate(4 * kWordSize)); // Pop arguments. 1195 __ addiu(SP, SP, Immediate(4 * kWordSize)); // Pop arguments.
1206 // V0: new object 1196 // V0: new object
1207 // Restore the frame pointer and return. 1197 // Restore the frame pointer and return.
1208 __ LeaveStubFrameAndReturn(RA, true); 1198 __ LeaveStubFrameAndReturn(RA, true);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
1292 1282
1293 // Set number of variables field to 1 (for captured receiver). 1283 // Set number of variables field to 1 (for captured receiver).
1294 __ LoadImmediate(T0, 1); 1284 __ LoadImmediate(T0, 1);
1295 __ sw(T0, Address(T4, Context::num_variables_offset())); 1285 __ sw(T0, Address(T4, Context::num_variables_offset()));
1296 1286
1297 // Set isolate field to isolate of current context. 1287 // Set isolate field to isolate of current context.
1298 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); 1288 __ lw(T0, FieldAddress(CTX, Context::isolate_offset()));
1299 __ sw(T0, Address(T4, Context::isolate_offset())); 1289 __ sw(T0, Address(T4, Context::isolate_offset()));
1300 1290
1301 // Set the parent to null. 1291 // Set the parent to null.
1302 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null())); 1292 __ sw(NULLREG, Address(T4, Context::parent_offset()));
1303 __ sw(T0, Address(T4, Context::parent_offset()));
1304 1293
1305 // Initialize the context variable to the receiver. 1294 // Initialize the context variable to the receiver.
1306 __ lw(T0, Address(FP, kReceiverFPOffset)); 1295 __ lw(T0, Address(FP, kReceiverFPOffset));
1307 __ sw(T0, Address(T4, Context::variable_offset(0))); 1296 __ sw(T0, Address(T4, Context::variable_offset(0)));
1308 1297
1309 // Set the newly allocated context in the newly allocated closure. 1298 // Set the newly allocated context in the newly allocated closure.
1310 __ AddImmediate(T1, T4, kHeapObjectTag); 1299 __ AddImmediate(T1, T4, kHeapObjectTag);
1311 __ sw(T1, Address(T2, Closure::context_offset())); 1300 __ sw(T1, Address(T2, Closure::context_offset()));
1312 } else { 1301 } else {
1313 __ sw(CTX, Address(T2, Closure::context_offset())); 1302 __ sw(CTX, Address(T2, Closure::context_offset()));
(...skipping 12 matching lines...) Expand all
1326 __ Bind(&slow_case); 1315 __ Bind(&slow_case);
1327 } 1316 }
1328 1317
1329 // If it's an implicit static closure we need 2 stack slots. Otherwise, 1318 // If it's an implicit static closure we need 2 stack slots. Otherwise,
1330 // If it's an implicit instance closure we need 4 stack slots, o/w only 3. 1319 // If it's an implicit instance closure we need 4 stack slots, o/w only 3.
1331 int num_slots = 2; 1320 int num_slots = 2;
1332 if (!is_implicit_static_closure) { 1321 if (!is_implicit_static_closure) {
1333 num_slots = is_implicit_instance_closure ? 4 : 3; 1322 num_slots = is_implicit_instance_closure ? 4 : 3;
1334 } 1323 }
1335 __ addiu(SP, SP, Immediate(-num_slots * kWordSize)); 1324 __ addiu(SP, SP, Immediate(-num_slots * kWordSize));
1336 __ LoadImmediate(V0, reinterpret_cast<intptr_t>(Object::null()));
1337 __ LoadObject(TMP1, func); 1325 __ LoadObject(TMP1, func);
1338 // Setup space on stack for return value. 1326 // Setup space on stack for return value.
1339 __ sw(V0, Address(SP, (num_slots - 1) * kWordSize)); 1327 __ sw(NULLREG, Address(SP, (num_slots - 1) * kWordSize));
1340 __ sw(TMP1, Address(SP, (num_slots - 2) * kWordSize)); 1328 __ sw(TMP1, Address(SP, (num_slots - 2) * kWordSize));
1341 if (is_implicit_static_closure) { 1329 if (is_implicit_static_closure) {
1342 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry); 1330 __ CallRuntime(kAllocateImplicitStaticClosureRuntimeEntry);
1343 __ TraceSimMsg("AllocationStubForClosure return"); 1331 __ TraceSimMsg("AllocationStubForClosure return");
1344 } else { 1332 } else {
1345 if (is_implicit_instance_closure) { 1333 if (is_implicit_instance_closure) {
1346 __ lw(T1, Address(FP, kReceiverFPOffset)); 1334 __ lw(T1, Address(FP, kReceiverFPOffset));
1347 __ sw(T1, Address(SP, (num_slots - 3) * kWordSize)); // Receiver. 1335 __ sw(T1, Address(SP, (num_slots - 3) * kWordSize)); // Receiver.
1348 __ sw(V0, Address(SP, (num_slots - 4) * kWordSize)); // Push null. 1336 __ sw(NULLREG, Address(SP, (num_slots - 4) * kWordSize)); // Push null.
1349 } 1337 }
1350 if (has_type_arguments) { 1338 if (has_type_arguments) {
1351 __ lw(V0, Address(FP, kTypeArgumentsFPOffset)); 1339 __ lw(V0, Address(FP, kTypeArgumentsFPOffset));
1352 // Push type arguments of closure. 1340 // Push type arguments of closure.
1353 __ sw(V0, Address(SP, (num_slots - 3) * kWordSize)); 1341 __ sw(V0, Address(SP, (num_slots - 3) * kWordSize));
1354 } 1342 }
1355 1343
1356 if (is_implicit_instance_closure) { 1344 if (is_implicit_instance_closure) {
1357 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry); 1345 __ CallRuntime(kAllocateImplicitInstanceClosureRuntimeEntry);
1358 __ TraceSimMsg("AllocationStubForClosure return"); 1346 __ TraceSimMsg("AllocationStubForClosure return");
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after
1536 1524
1537 // Compute address of arguments (first read number of arguments from 1525 // Compute address of arguments (first read number of arguments from
1538 // arguments descriptor array and then compute address on the stack). 1526 // arguments descriptor array and then compute address on the stack).
1539 // T1: argument_count - 1 (smi). 1527 // T1: argument_count - 1 (smi).
1540 __ sll(T1, T1, 1); // T1 is Smi. 1528 __ sll(T1, T1, 1); // T1 is Smi.
1541 __ addu(T1, SP, T1); 1529 __ addu(T1, SP, T1);
1542 // T1: address of receiver. 1530 // T1: address of receiver.
1543 // Create a stub frame as we are pushing some objects on the stack before 1531 // Create a stub frame as we are pushing some objects on the stack before
1544 // calling into the runtime. 1532 // calling into the runtime.
1545 __ EnterStubFrame(); 1533 __ EnterStubFrame();
1546 __ LoadImmediate(T3, reinterpret_cast<intptr_t>(Object::null()));
1547 // Preserve IC data object and arguments descriptor array and 1534 // Preserve IC data object and arguments descriptor array and
1548 // setup space on stack for result (target code object). 1535 // setup space on stack for result (target code object).
1549 int num_slots = num_args + 5; 1536 int num_slots = num_args + 5;
1550 __ addiu(SP, SP, Immediate(-num_slots * kWordSize)); 1537 __ addiu(SP, SP, Immediate(-num_slots * kWordSize));
1551 __ sw(S5, Address(SP, (num_slots - 1) * kWordSize)); 1538 __ sw(S5, Address(SP, (num_slots - 1) * kWordSize));
1552 __ sw(S4, Address(SP, (num_slots - 2) * kWordSize)); 1539 __ sw(S4, Address(SP, (num_slots - 2) * kWordSize));
1553 __ sw(T3, Address(SP, (num_slots - 3) * kWordSize)); 1540 __ sw(NULLREG, Address(SP, (num_slots - 3) * kWordSize));
1554 // Push call arguments. 1541 // Push call arguments.
1555 for (intptr_t i = 0; i < num_args; i++) { 1542 for (intptr_t i = 0; i < num_args; i++) {
1556 __ lw(TMP1, Address(T1, -i * kWordSize)); 1543 __ lw(TMP1, Address(T1, -i * kWordSize));
1557 __ sw(TMP1, Address(SP, (num_slots - i - 4) * kWordSize)); 1544 __ sw(TMP1, Address(SP, (num_slots - i - 4) * kWordSize));
1558 } 1545 }
1559 // Pass IC data object and arguments descriptor array. 1546 // Pass IC data object and arguments descriptor array.
1560 __ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize)); 1547 __ sw(S5, Address(SP, (num_slots - num_args - 4) * kWordSize));
1561 __ sw(S4, Address(SP, (num_slots - num_args - 5) * kWordSize)); 1548 __ sw(S4, Address(SP, (num_slots - num_args - 5) * kWordSize));
1562 1549
1563 if (num_args == 1) { 1550 if (num_args == 1) {
1564 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry); 1551 __ CallRuntime(kInlineCacheMissHandlerOneArgRuntimeEntry);
1565 } else if (num_args == 2) { 1552 } else if (num_args == 2) {
1566 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry); 1553 __ CallRuntime(kInlineCacheMissHandlerTwoArgsRuntimeEntry);
1567 } else if (num_args == 3) { 1554 } else if (num_args == 3) {
1568 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry); 1555 __ CallRuntime(kInlineCacheMissHandlerThreeArgsRuntimeEntry);
1569 } else { 1556 } else {
1570 UNIMPLEMENTED(); 1557 UNIMPLEMENTED();
1571 } 1558 }
1572 __ TraceSimMsg("NArgsCheckInlineCacheStub return"); 1559 __ TraceSimMsg("NArgsCheckInlineCacheStub return");
1573 // Pop returned code object into T3 (null if not found). 1560 // Pop returned code object into T3 (null if not found).
1574 // Restore arguments descriptor array and IC data array. 1561 // Restore arguments descriptor array and IC data array.
1575 __ lw(T3, Address(SP, (num_slots - 3) * kWordSize)); 1562 __ lw(T3, Address(SP, (num_slots - 3) * kWordSize));
1576 __ lw(S4, Address(SP, (num_slots - 2) * kWordSize)); 1563 __ lw(S4, Address(SP, (num_slots - 2) * kWordSize));
1577 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize)); 1564 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize));
1578 // Remove the call arguments pushed earlier, including the IC data object 1565 // Remove the call arguments pushed earlier, including the IC data object
1579 // and the arguments descriptor array. 1566 // and the arguments descriptor array.
1580 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); 1567 __ addiu(SP, SP, Immediate(num_slots * kWordSize));
1581 __ LeaveStubFrame(); 1568 __ LeaveStubFrame();
1582 Label call_target_function; 1569 Label call_target_function;
1583 __ BranchNotEqual(T3, reinterpret_cast<intptr_t>(Object::null()), 1570 __ bne(T3, NULLREG, &call_target_function);
1584 &call_target_function); 1571
1585 // NoSuchMethod or closure. 1572 // NoSuchMethod or closure.
1586 // Mark IC call that it may be a closure call that does not collect 1573 // Mark IC call that it may be a closure call that does not collect
1587 // type feedback. 1574 // type feedback.
1588 __ LoadImmediate(TMP2, 1); 1575 __ LoadImmediate(TMP1, 1);
1589 __ Branch(&StubCode::InstanceFunctionLookupLabel()); 1576 __ Branch(&StubCode::InstanceFunctionLookupLabel());
1590 __ delay_slot()->sb(TMP2, FieldAddress(S5, ICData::is_closure_call_offset())); 1577 __ delay_slot()->sb(TMP1, FieldAddress(S5, ICData::is_closure_call_offset()));
1591 1578
1592 __ Bind(&found); 1579 __ Bind(&found);
1593 // T0: Pointer to an IC data check group. 1580 // T0: Pointer to an IC data check group.
1594 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1581 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1595 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1582 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1596 __ lw(T3, Address(T0, target_offset)); 1583 __ lw(T3, Address(T0, target_offset));
1597 __ lw(T4, Address(T0, count_offset)); 1584 __ lw(T4, Address(T0, count_offset));
1598 1585
1599 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5); 1586 __ AddImmediateDetectOverflow(T4, T4, Smi::RawValue(1), T5, T6);
1600 1587
1601 __ bgez(T5, &call_target_function); // No overflow. 1588 __ bgez(T5, &call_target_function); // No overflow.
1602 __ delay_slot()->sw(T4, Address(T0, count_offset)); 1589 __ delay_slot()->sw(T4, Address(T0, count_offset));
1603 1590
1604 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); 1591 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue));
1605 __ sw(T1, Address(T0, count_offset)); 1592 __ sw(T1, Address(T0, count_offset));
1606 1593
1607 __ Bind(&call_target_function); 1594 __ Bind(&call_target_function);
1608 // T3: Target function. 1595 // T3: Target function.
1609 __ lw(T3, FieldAddress(T3, Function::code_offset())); 1596 __ lw(T3, FieldAddress(T3, Function::code_offset()));
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after
1689 } 1676 }
1690 1677
1691 1678
1692 // RA: return address (Dart code). 1679 // RA: return address (Dart code).
1693 // S4: Arguments descriptor array. 1680 // S4: Arguments descriptor array.
1694 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) { 1681 void StubCode::GenerateBreakpointStaticStub(Assembler* assembler) {
1695 __ TraceSimMsg("BreakpointStaticStub"); 1682 __ TraceSimMsg("BreakpointStaticStub");
1696 // Create a stub frame as we are pushing some objects on the stack before 1683 // Create a stub frame as we are pushing some objects on the stack before
1697 // calling into the runtime. 1684 // calling into the runtime.
1698 __ EnterStubFrame(); 1685 __ EnterStubFrame();
1699 __ LoadImmediate(T0, reinterpret_cast<intptr_t>(Object::null()));
1700 // Preserve arguments descriptor and make room for result. 1686 // Preserve arguments descriptor and make room for result.
1701 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 1687 __ addiu(SP, SP, Immediate(-2 * kWordSize));
1702 __ sw(S4, Address(SP, 1 * kWordSize)); 1688 __ sw(S4, Address(SP, 1 * kWordSize));
1703 __ sw(T0, Address(SP, 0 * kWordSize)); 1689 __ sw(NULLREG, Address(SP, 0 * kWordSize));
1704 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry); 1690 __ CallRuntime(kBreakpointStaticHandlerRuntimeEntry);
1705 // Pop code object result and restore arguments descriptor. 1691 // Pop code object result and restore arguments descriptor.
1706 __ lw(T0, Address(SP, 0 * kWordSize)); 1692 __ lw(T0, Address(SP, 0 * kWordSize));
1707 __ lw(S4, Address(SP, 1 * kWordSize)); 1693 __ lw(S4, Address(SP, 1 * kWordSize));
1708 __ addiu(SP, SP, Immediate(2 * kWordSize)); 1694 __ addiu(SP, SP, Immediate(2 * kWordSize));
1709 __ LeaveStubFrame(); 1695 __ LeaveStubFrame();
1710 1696
1711 // Now call the static function. The breakpoint handler function 1697 // Now call the static function. The breakpoint handler function
1712 // ensures that the call target is compiled. 1698 // ensures that the call target is compiled.
1713 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); 1699 __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
1714 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag); 1700 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag);
1715 __ jr(T0); 1701 __ jr(T0);
1716 } 1702 }
1717 1703
1718 1704
1719 // V0: return value. 1705 // V0: return value.
1720 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) { 1706 void StubCode::GenerateBreakpointReturnStub(Assembler* assembler) {
1721 __ TraceSimMsg("BreakpoingReturnStub"); 1707 __ TraceSimMsg("BreakpoingReturnStub");
1722 // Create a stub frame as we are pushing some objects on the stack before 1708 // Create a stub frame as we are pushing some objects on the stack before
1723 // calling into the runtime. 1709 // calling into the runtime.
1724 __ EnterStubFrame(); 1710 __ EnterStubFrame();
1725 __ Push(V0); 1711 __ Push(V0);
1726 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry); 1712 __ CallRuntime(kBreakpointReturnHandlerRuntimeEntry);
1727 __ Pop(V0); 1713 __ Pop(V0);
1728 __ LeaveStubFrame(); 1714 __ LeaveStubFrame();
1729 1715
1730 // Instead of returning to the patched Dart function, emulate the 1716 // Instead of returning to the patched Dart function, emulate the
1731 // smashed return code pattern and return to the function's caller. 1717 // smashed return code pattern and return to the function's caller.
1732 __ LeaveDartFrame(); 1718 __ LeaveDartFrameAndReturn();
1733 __ Ret();
1734 } 1719 }
1735 1720
1736 1721
1737 // RA: return address (Dart code). 1722 // RA: return address (Dart code).
1738 // S5: Inline cache data array. 1723 // S5: Inline cache data array.
1739 // S4: Arguments descriptor array. 1724 // S4: Arguments descriptor array.
1740 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { 1725 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) {
1741 // Create a stub frame as we are pushing some objects on the stack before 1726 // Create a stub frame as we are pushing some objects on the stack before
1742 // calling into the runtime. 1727 // calling into the runtime.
1743 __ EnterStubFrame(); 1728 __ EnterStubFrame();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
1776 // A2: cache array. 1761 // A2: cache array.
1777 // Result in V0: null -> not found, otherwise result (true or false). 1762 // Result in V0: null -> not found, otherwise result (true or false).
1778 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) { 1763 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
1779 __ TraceSimMsg("SubtypeNTestCacheStub"); 1764 __ TraceSimMsg("SubtypeNTestCacheStub");
1780 ASSERT((1 <= n) && (n <= 3)); 1765 ASSERT((1 <= n) && (n <= 3));
1781 if (n > 1) { 1766 if (n > 1) {
1782 // Get instance type arguments. 1767 // Get instance type arguments.
1783 __ LoadClass(T0, A0); 1768 __ LoadClass(T0, A0);
1784 // Compute instance type arguments into R4. 1769 // Compute instance type arguments into R4.
1785 Label has_no_type_arguments; 1770 Label has_no_type_arguments;
1786 __ LoadImmediate(T1, reinterpret_cast<intptr_t>(Object::null()));
1787 __ lw(T2, FieldAddress(T0, 1771 __ lw(T2, FieldAddress(T0,
1788 Class::type_arguments_field_offset_in_words_offset())); 1772 Class::type_arguments_field_offset_in_words_offset()));
1789 __ BranchEqual(T2, Class::kNoTypeArguments, &has_no_type_arguments); 1773 __ BranchEqual(T2, Class::kNoTypeArguments, &has_no_type_arguments);
1790 __ sll(T2, T2, 2); 1774 __ sll(T2, T2, 2);
1791 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4 1775 __ addu(T2, A0, T2); // T2 <- A0 + T2 * 4
1792 __ lw(T1, FieldAddress(T2, 0)); 1776 __ lw(T1, FieldAddress(T2, 0));
1793 __ Bind(&has_no_type_arguments); 1777 __ Bind(&has_no_type_arguments);
1794 } 1778 }
1795 __ LoadClassId(T0, A0); 1779 __ LoadClassId(T0, A0);
1796 // A0: instance. 1780 // A0: instance.
1797 // A1: instantiator type arguments or NULL. 1781 // A1: instantiator type arguments or NULL.
1798 // A2: SubtypeTestCache. 1782 // A2: SubtypeTestCache.
1799 // T0: instance class id. 1783 // T0: instance class id.
1800 // T1: instance type arguments (null if none), used only if n > 1. 1784 // T1: instance type arguments (null if none), used only if n > 1.
1801 __ lw(T2, FieldAddress(A2, SubtypeTestCache::cache_offset())); 1785 __ lw(T2, FieldAddress(A2, SubtypeTestCache::cache_offset()));
1802 __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag); 1786 __ AddImmediate(T2, Array::data_offset() - kHeapObjectTag);
1803 1787
1804 Label loop, found, not_found, next_iteration; 1788 Label loop, found, not_found, next_iteration;
1805 // T0: instance class id. 1789 // T0: instance class id.
1806 // T1: instance type arguments. 1790 // T1: instance type arguments.
1807 // T2: Entry start. 1791 // T2: Entry start.
1808 __ SmiTag(T0); 1792 __ SmiTag(T0);
1809 __ Bind(&loop); 1793 __ Bind(&loop);
1810 __ lw(T3, Address(T2, kWordSize * SubtypeTestCache::kInstanceClassId)); 1794 __ lw(T3, Address(T2, kWordSize * SubtypeTestCache::kInstanceClassId));
1811 __ BranchEqual(T3, reinterpret_cast<intptr_t>(Object::null()), &not_found); 1795 __ beq(T3, NULLREG, &not_found);
1812 1796
1813 if (n == 1) { 1797 if (n == 1) {
1814 __ beq(T3, T0, &found); 1798 __ beq(T3, T0, &found);
1815 } else { 1799 } else {
1816 __ bne(T3, T0, &next_iteration); 1800 __ bne(T3, T0, &next_iteration);
1817 __ lw(T3, 1801 __ lw(T3,
1818 Address(T2, kWordSize * SubtypeTestCache::kInstanceTypeArguments)); 1802 Address(T2, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
1819 if (n == 2) { 1803 if (n == 2) {
1820 __ beq(T3, T1, &found); 1804 __ beq(T3, T1, &found);
1821 } else { 1805 } else {
1822 __ bne(T3, T1, &next_iteration); 1806 __ bne(T3, T1, &next_iteration);
1823 __ lw(T3, Address(T2, kWordSize * 1807 __ lw(T3, Address(T2, kWordSize *
1824 SubtypeTestCache::kInstantiatorTypeArguments)); 1808 SubtypeTestCache::kInstantiatorTypeArguments));
1825 __ beq(T3, A1, &found); 1809 __ beq(T3, A1, &found);
1826 } 1810 }
1827 } 1811 }
1828 __ Bind(&next_iteration); 1812 __ Bind(&next_iteration);
1829 __ b(&loop); 1813 __ b(&loop);
1830 __ delay_slot()->addiu(T2, T2, 1814 __ delay_slot()->addiu(T2, T2,
1831 Immediate(kWordSize * SubtypeTestCache::kTestEntryLength)); 1815 Immediate(kWordSize * SubtypeTestCache::kTestEntryLength));
1832 // Fall through to not found. 1816 // Fall through to not found.
1833 __ Bind(&not_found); 1817 __ Bind(&not_found);
1834 intptr_t null = reinterpret_cast<intptr_t>(Object::null());
1835 uint16_t null_lo = Utils::Low16Bits(null);
1836 uint16_t null_hi = Utils::High16Bits(null);
1837 __ lui(V0, Immediate(null_hi));
1838 __ Ret(); 1818 __ Ret();
1839 __ delay_slot()->ori(V0, V0, Immediate(null_lo)); 1819 __ delay_slot()->mov(V0, NULLREG);
1840 1820
1841 __ Bind(&found); 1821 __ Bind(&found);
1842 __ Ret(); 1822 __ Ret();
1843 __ delay_slot()->lw(V0, 1823 __ delay_slot()->lw(V0,
1844 Address(T2, kWordSize * SubtypeTestCache::kTestResult)); 1824 Address(T2, kWordSize * SubtypeTestCache::kTestResult));
1845 } 1825 }
1846 1826
1847 1827
1848 // Used to check class and type arguments. Arguments passed in registers: 1828 // Used to check class and type arguments. Arguments passed in registers:
1849 // RA: return address. 1829 // RA: return address.
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after
1955 } 1935 }
1956 1936
1957 Label update_ic_data; 1937 Label update_ic_data;
1958 __ b(&update_ic_data); 1938 __ b(&update_ic_data);
1959 1939
1960 __ Bind(&found); 1940 __ Bind(&found);
1961 const intptr_t count_offset = 1941 const intptr_t count_offset =
1962 ICData::CountIndexFor(kNumArgsTested) * kWordSize; 1942 ICData::CountIndexFor(kNumArgsTested) * kWordSize;
1963 Label no_overflow; 1943 Label no_overflow;
1964 __ lw(T1, Address(T6, count_offset)); 1944 __ lw(T1, Address(T6, count_offset));
1965 __ AddImmediateDetectOverflow(T1, T1, Smi::RawValue(1), CMPRES); 1945 __ AddImmediateDetectOverflow(T1, T1, Smi::RawValue(1), CMPRES, T6);
1966 __ bgez(CMPRES, &no_overflow); 1946 __ bgez(CMPRES, &no_overflow);
1967 __ LoadImmediate(TMP1, Smi::RawValue(Smi::kMaxValue)); 1947 __ LoadImmediate(TMP1, Smi::RawValue(Smi::kMaxValue));
1968 __ sw(TMP1, Address(T6, count_offset)); // If overflow. 1948 __ sw(TMP1, Address(T6, count_offset)); // If overflow.
1969 __ Bind(&no_overflow); 1949 __ Bind(&no_overflow);
1970 1950
1971 Label compute_result; 1951 Label compute_result;
1972 __ Bind(&compute_result); 1952 __ Bind(&compute_result);
1973 __ LoadObject(TMP1, Bool::True()); 1953 __ LoadObject(T4, Bool::True());
1974 __ LoadObject(TMP2, Bool::False()); 1954 __ LoadObject(T5, Bool::False());
1975 __ subu(CMPRES, A0, A1); 1955 __ subu(CMPRES, A0, A1);
1976 __ movz(V0, TMP1, CMPRES); 1956 __ movz(V0, T4, CMPRES);
1977 __ movn(V0, TMP2, CMPRES); 1957 __ movn(V0, T5, CMPRES);
1978 __ LeaveStubFrameAndReturn(); 1958 __ LeaveStubFrameAndReturn();
1979 1959
1980 __ Bind(&get_class_id_as_smi); 1960 __ Bind(&get_class_id_as_smi);
1981 // Test if Smi -> load Smi class for comparison. 1961 // Test if Smi -> load Smi class for comparison.
1982 Label not_smi; 1962 Label not_smi;
1983 __ andi(CMPRES, T2, Immediate(kSmiTagMask)); 1963 __ andi(CMPRES, T2, Immediate(kSmiTagMask));
1984 __ bne(CMPRES, ZR, &not_smi); 1964 __ bne(CMPRES, ZR, &not_smi);
1985 __ jr(RA); 1965 __ jr(RA);
1986 __ delay_slot()->addiu(T2, ZR, Immediate(Smi::RawValue(kSmiCid))); 1966 __ delay_slot()->addiu(T2, ZR, Immediate(Smi::RawValue(kSmiCid)));
1987 __ Bind(&not_smi); 1967 __ Bind(&not_smi);
(...skipping 19 matching lines...) Expand all
2007 1987
2008 // Calls to the runtime to optimize the given function. 1988 // Calls to the runtime to optimize the given function.
2009 // T0: function to be reoptimized. 1989 // T0: function to be reoptimized.
2010 // S4: argument descriptor (preserved). 1990 // S4: argument descriptor (preserved).
2011 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) { 1991 void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
2012 __ TraceSimMsg("OptimizeFunctionStub"); 1992 __ TraceSimMsg("OptimizeFunctionStub");
2013 __ EnterStubFrame(); 1993 __ EnterStubFrame();
2014 __ addiu(SP, SP, Immediate(-3 * kWordSize)); 1994 __ addiu(SP, SP, Immediate(-3 * kWordSize));
2015 __ sw(S4, Address(SP, 2 * kWordSize)); 1995 __ sw(S4, Address(SP, 2 * kWordSize));
2016 // Setup space on stack for return value. 1996 // Setup space on stack for return value.
2017 __ LoadImmediate(TMP, reinterpret_cast<intptr_t>(Object::null())); 1997 __ sw(NULLREG, Address(SP, 1 * kWordSize));
2018 __ sw(TMP1, Address(SP, 1 * kWordSize));
2019 __ sw(T0, Address(SP, 0 * kWordSize)); 1998 __ sw(T0, Address(SP, 0 * kWordSize));
2020 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry); 1999 __ CallRuntime(kOptimizeInvokedFunctionRuntimeEntry);
2021 __ TraceSimMsg("OptimizeFunctionStub return"); 2000 __ TraceSimMsg("OptimizeFunctionStub return");
2022 __ lw(T0, Address(SP, 1 * kWordSize)); // Get Code object 2001 __ lw(T0, Address(SP, 1 * kWordSize)); // Get Code object
2023 __ lw(S4, Address(SP, 2 * kWordSize)); // Restore argument descriptor. 2002 __ lw(S4, Address(SP, 2 * kWordSize)); // Restore argument descriptor.
2024 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Discard argument. 2003 __ addiu(SP, SP, Immediate(3 * kWordSize)); // Discard argument.
2025 2004
2026 __ lw(T0, FieldAddress(T0, Code::instructions_offset())); 2005 __ lw(T0, FieldAddress(T0, Code::instructions_offset()));
2027 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag); 2006 __ AddImmediate(T0, Instructions::HeaderSize() - kHeapObjectTag);
2028 __ LeaveStubFrameAndReturn(T0); 2007 __ LeaveStubFrameAndReturn(T0);
(...skipping 11 matching lines...) Expand all
2040 // checks for boxed numbers. 2019 // checks for boxed numbers.
2041 // RA: return address. 2020 // RA: return address.
2042 // SP + 4: left operand. 2021 // SP + 4: left operand.
2043 // SP + 0: right operand. 2022 // SP + 0: right operand.
2044 // Return: CMPRES is zero if equal, non-zero otherwise. 2023 // Return: CMPRES is zero if equal, non-zero otherwise.
2045 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint 2024 // Note: A Mint cannot contain a value that would fit in Smi, a Bigint
2046 // cannot contain a value that fits in Mint or Smi. 2025 // cannot contain a value that fits in Mint or Smi.
2047 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) { 2026 void StubCode::GenerateIdenticalWithNumberCheckStub(Assembler* assembler) {
2048 __ TraceSimMsg("IdenticalWithNumberCheckStub"); 2027 __ TraceSimMsg("IdenticalWithNumberCheckStub");
2049 const Register ret = CMPRES; 2028 const Register ret = CMPRES;
2050 const Register temp1 = TMP1; 2029 const Register temp1 = T2;
2051 const Register temp2 = TMP2; 2030 const Register temp2 = T3;
2052 const Register left = T1; 2031 const Register left = T1;
2053 const Register right = T0; 2032 const Register right = T0;
2054 // Preserve left, right. 2033 // Preserve left, right.
2055 __ addiu(SP, SP, Immediate(-2 * kWordSize)); 2034 __ addiu(SP, SP, Immediate(-2 * kWordSize));
2056 __ sw(T1, Address(SP, 1 * kWordSize)); 2035 __ sw(T1, Address(SP, 1 * kWordSize));
2057 __ sw(T0, Address(SP, 0 * kWordSize)); 2036 __ sw(T0, Address(SP, 0 * kWordSize));
2058 // TOS + 3: left argument. 2037 // TOS + 3: left argument.
2059 // TOS + 2: right argument. 2038 // TOS + 2: right argument.
2060 // TOS + 1: saved left 2039 // TOS + 1: saved left
2061 // TOS + 0: saved right 2040 // TOS + 0: saved right
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2127 __ Bind(&done); 2106 __ Bind(&done);
2128 __ lw(T0, Address(SP, 0 * kWordSize)); 2107 __ lw(T0, Address(SP, 0 * kWordSize));
2129 __ lw(T1, Address(SP, 1 * kWordSize)); 2108 __ lw(T1, Address(SP, 1 * kWordSize));
2130 __ Ret(); 2109 __ Ret();
2131 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize)); 2110 __ delay_slot()->addiu(SP, SP, Immediate(2 * kWordSize));
2132 } 2111 }
2133 2112
2134 } // namespace dart 2113 } // namespace dart
2135 2114
2136 #endif // defined TARGET_ARCH_MIPS 2115 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_arm.cc ('k') | runtime/vm/stub_code_mips_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698