| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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, ¬_closure); | 642 __ beq(T1, NULLREG, ¬_closure); |
| 649 | 643 |
| 650 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); | 644 __ andi(CMPRES, T1, Immediate(kSmiTagMask)); |
| 651 __ beq(CMPRES, ZR, ¬_closure); // Not a closure, but a smi. | 645 __ beq(CMPRES, ZR, ¬_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, ¬_closure); | 653 __ beq(T0, NULLREG, ¬_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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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()), ¬_found); | 1795 __ beq(T3, NULLREG, ¬_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(¬_found); | 1817 __ Bind(¬_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 Loading... |
| 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, ¬_smi); | 1964 __ bne(CMPRES, ZR, ¬_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(¬_smi); | 1967 __ Bind(¬_smi); |
| (...skipping 19 matching lines...) Expand all Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |