| 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/runtime_entry.h" | 9 #include "vm/runtime_entry.h" |
| 10 #include "vm/simulator.h" | 10 #include "vm/simulator.h" |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 } | 201 } |
| 202 | 202 |
| 203 | 203 |
| 204 void Assembler::CompareObject(Register rd, Register rn, const Object& object) { | 204 void Assembler::CompareObject(Register rd, Register rn, const Object& object) { |
| 205 ASSERT(rn != TMP1); | 205 ASSERT(rn != TMP1); |
| 206 LoadObject(TMP1, object); | 206 LoadObject(TMP1, object); |
| 207 subu(rd, rn, TMP1); | 207 subu(rd, rn, TMP1); |
| 208 } | 208 } |
| 209 | 209 |
| 210 | 210 |
| 211 // Preserves object and value registers. |
| 212 void Assembler::StoreIntoObjectFilterNoSmi(Register object, |
| 213 Register value, |
| 214 Label* no_update) { |
| 215 COMPILE_ASSERT((kNewObjectAlignmentOffset == kWordSize) && |
| 216 (kOldObjectAlignmentOffset == 0), young_alignment); |
| 217 |
| 218 // Write-barrier triggers if the value is in the new space (has bit set) and |
| 219 // the object is in the old space (has bit cleared). |
| 220 // To check that, we compute value & ~object and skip the write barrier |
| 221 // if the bit is not set. We can't destroy the object. |
| 222 nor(TMP1, ZR, object); |
| 223 and_(TMP1, value, TMP1); |
| 224 andi(TMP1, TMP1, Immediate(kNewObjectAlignmentOffset)); |
| 225 beq(TMP1, ZR, no_update); |
| 226 } |
| 227 |
| 228 |
| 229 // Preserves object and value registers. |
| 230 void Assembler::StoreIntoObjectFilter(Register object, |
| 231 Register value, |
| 232 Label* no_update) { |
| 233 // For the value we are only interested in the new/old bit and the tag bit. |
| 234 // And the new bit with the tag bit. The resulting bit will be 0 for a Smi. |
| 235 sll(TMP1, value, kObjectAlignmentLog2 - 1); |
| 236 and_(TMP1, value, TMP1); |
| 237 // And the result with the negated space bit of the object. |
| 238 nor(TMP2, ZR, object); |
| 239 and_(TMP1, TMP1, TMP2); |
| 240 andi(TMP1, TMP1, Immediate(kNewObjectAlignmentOffset)); |
| 241 beq(TMP1, ZR, no_update); |
| 242 } |
| 243 |
| 244 |
| 245 void Assembler::StoreIntoObject(Register object, |
| 246 const Address& dest, |
| 247 Register value, |
| 248 bool can_value_be_smi) { |
| 249 ASSERT(object != value); |
| 250 sw(value, dest); |
| 251 Label done; |
| 252 if (can_value_be_smi) { |
| 253 StoreIntoObjectFilter(object, value, &done); |
| 254 } else { |
| 255 StoreIntoObjectFilterNoSmi(object, value, &done); |
| 256 } |
| 257 // A store buffer update is required. |
| 258 if (value != T0) Push(T0); // Preserve T0. |
| 259 if (object != T0) { |
| 260 mov(T0, object); |
| 261 } |
| 262 BranchLink(&StubCode::UpdateStoreBufferLabel()); |
| 263 if (value != T0) Pop(T0); // Restore T0. |
| 264 Bind(&done); |
| 265 } |
| 266 |
| 267 |
| 268 void Assembler::StoreIntoObjectNoBarrier(Register object, |
| 269 const Address& dest, |
| 270 Register value) { |
| 271 sw(value, dest); |
| 272 #if defined(DEBUG) |
| 273 Label done; |
| 274 StoreIntoObjectFilter(object, value, &done); |
| 275 Stop("Store buffer update is required"); |
| 276 Bind(&done); |
| 277 #endif // defined(DEBUG) |
| 278 // No store buffer update. |
| 279 } |
| 280 |
| 281 |
| 282 void Assembler::StoreIntoObjectNoBarrier(Register object, |
| 283 const Address& dest, |
| 284 const Object& value) { |
| 285 ASSERT(value.IsSmi() || value.InVMHeap() || |
| 286 (value.IsOld() && value.IsNotTemporaryScopedHandle())); |
| 287 // No store buffer update. |
| 288 LoadObject(TMP1, value); |
| 289 sw(TMP1, dest); |
| 290 } |
| 291 |
| 292 |
| 211 void Assembler::LoadClassId(Register result, Register object) { | 293 void Assembler::LoadClassId(Register result, Register object) { |
| 212 ASSERT(RawObject::kClassIdTagBit == 16); | 294 ASSERT(RawObject::kClassIdTagBit == 16); |
| 213 ASSERT(RawObject::kClassIdTagSize == 16); | 295 ASSERT(RawObject::kClassIdTagSize == 16); |
| 214 const intptr_t class_id_offset = Object::tags_offset() + | 296 const intptr_t class_id_offset = Object::tags_offset() + |
| 215 RawObject::kClassIdTagBit / kBitsPerByte; | 297 RawObject::kClassIdTagBit / kBitsPerByte; |
| 216 lhu(result, FieldAddress(object, class_id_offset)); | 298 lhu(result, FieldAddress(object, class_id_offset)); |
| 217 } | 299 } |
| 218 | 300 |
| 219 | 301 |
| 220 void Assembler::LoadClassById(Register result, Register class_id) { | 302 void Assembler::LoadClassById(Register result, Register class_id) { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 353 // Reserve space for arguments and align frame before entering | 435 // Reserve space for arguments and align frame before entering |
| 354 // the C++ world. | 436 // the C++ world. |
| 355 AddImmediate(SP, -frame_space); | 437 AddImmediate(SP, -frame_space); |
| 356 if (OS::ActivationFrameAlignment() > 0) { | 438 if (OS::ActivationFrameAlignment() > 0) { |
| 357 LoadImmediate(TMP1, ~(OS::ActivationFrameAlignment() - 1)); | 439 LoadImmediate(TMP1, ~(OS::ActivationFrameAlignment() - 1)); |
| 358 and_(SP, SP, TMP1); | 440 and_(SP, SP, TMP1); |
| 359 } | 441 } |
| 360 } | 442 } |
| 361 | 443 |
| 362 | 444 |
| 445 void Assembler::EnterCallRuntimeFrame(intptr_t frame_space) { |
| 446 const intptr_t kPushedRegistersSize = |
| 447 kDartVolatileCpuRegCount * kWordSize + |
| 448 2 * kWordSize + // FP and RA. |
| 449 kDartVolatileFpuRegCount * kWordSize; |
| 450 |
| 451 if (prologue_offset_ == -1) { |
| 452 prologue_offset_ = CodeSize(); |
| 453 } |
| 454 |
| 455 // Save volatile CPU and FPU registers on the stack: |
| 456 // ------------- |
| 457 // FPU Registers |
| 458 // CPU Registers |
| 459 // RA |
| 460 // FP |
| 461 // ------------- |
| 462 // TODO(zra): It may be a problem for walking the stack that FP is below |
| 463 // the saved registers. If it turns out to be a problem in the |
| 464 // future, try pushing RA and FP before the volatile registers. |
| 465 addiu(SP, SP, Immediate(-kPushedRegistersSize)); |
| 466 for (int i = kDartFirstVolatileFpuReg; i <= kDartLastVolatileFpuReg; i++) { |
| 467 // These go above the volatile CPU registers. |
| 468 const int slot = |
| 469 (i - kDartFirstVolatileFpuReg) + kDartVolatileCpuRegCount + 2; |
| 470 FRegister reg = static_cast<FRegister>(i); |
| 471 swc1(reg, Address(SP, slot * kWordSize)); |
| 472 } |
| 473 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { |
| 474 // + 2 because FP goes in slot 0. |
| 475 const int slot = (i - kDartFirstVolatileCpuReg) + 2; |
| 476 Register reg = static_cast<Register>(i); |
| 477 sw(reg, Address(SP, slot * kWordSize)); |
| 478 } |
| 479 sw(RA, Address(SP, 1 * kWordSize)); |
| 480 sw(FP, Address(SP, 0 * kWordSize)); |
| 481 mov(FP, SP); |
| 482 |
| 483 ReserveAlignedFrameSpace(frame_space); |
| 484 } |
| 485 |
| 486 |
| 487 void Assembler::LeaveCallRuntimeFrame() { |
| 488 const intptr_t kPushedRegistersSize = |
| 489 kDartVolatileCpuRegCount * kWordSize + |
| 490 2 * kWordSize + // FP and RA. |
| 491 kDartVolatileFpuRegCount * kWordSize; |
| 492 |
| 493 // SP might have been modified to reserve space for arguments |
| 494 // and ensure proper alignment of the stack frame. |
| 495 // We need to restore it before restoring registers. |
| 496 mov(SP, FP); |
| 497 |
| 498 // Restore volatile CPU and FPU registers from the stack. |
| 499 lw(FP, Address(SP, 0 * kWordSize)); |
| 500 lw(RA, Address(SP, 1 * kWordSize)); |
| 501 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { |
| 502 // + 2 because FP goes in slot 0. |
| 503 const int slot = (i - kDartFirstVolatileCpuReg) + 2; |
| 504 Register reg = static_cast<Register>(i); |
| 505 lw(reg, Address(SP, slot * kWordSize)); |
| 506 } |
| 507 for (int i = kDartFirstVolatileFpuReg; i <= kDartLastVolatileFpuReg; i++) { |
| 508 // These go above the volatile CPU registers. |
| 509 const int slot = |
| 510 (i - kDartFirstVolatileFpuReg) + kDartVolatileCpuRegCount + 2; |
| 511 FRegister reg = static_cast<FRegister>(i); |
| 512 lwc1(reg, Address(SP, slot * kWordSize)); |
| 513 } |
| 514 addiu(SP, SP, Immediate(kPushedRegistersSize)); |
| 515 } |
| 516 |
| 517 |
| 363 int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { | 518 int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { |
| 364 if (object_pool_.IsNull()) { | 519 if (object_pool_.IsNull()) { |
| 365 // The object pool cannot be used in the vm isolate. | 520 // The object pool cannot be used in the vm isolate. |
| 366 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 521 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 367 object_pool_ = GrowableObjectArray::New(Heap::kOld); | 522 object_pool_ = GrowableObjectArray::New(Heap::kOld); |
| 368 } | 523 } |
| 369 const word address = label->address(); | 524 const word address = label->address(); |
| 370 ASSERT(Utils::IsAligned(address, 4)); | 525 ASSERT(Utils::IsAligned(address, 4)); |
| 371 // The address is stored in the object array as a RawSmi. | 526 // The address is stored in the object array as a RawSmi. |
| 372 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); | 527 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 385 b(&stop); | 540 b(&stop); |
| 386 Emit(reinterpret_cast<int32_t>(message)); | 541 Emit(reinterpret_cast<int32_t>(message)); |
| 387 Bind(&stop); | 542 Bind(&stop); |
| 388 break_(Instr::kStopMessageCode); | 543 break_(Instr::kStopMessageCode); |
| 389 } | 544 } |
| 390 | 545 |
| 391 } // namespace dart | 546 } // namespace dart |
| 392 | 547 |
| 393 #endif // defined TARGET_ARCH_MIPS | 548 #endif // defined TARGET_ARCH_MIPS |
| 394 | 549 |
| OLD | NEW |