Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 #include "vm/globals.h" | 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 // ------------- | |
|
regis
2013/04/16 00:16:38
I would add a TODO to verify that this layout is u
zra
2013/04/16 00:24:42
Done.
| |
| 462 addiu(SP, SP, Immediate(-kPushedRegistersSize)); | |
| 463 for (int i = kDartFirstVolatileFpuReg; i <= kDartLastVolatileFpuReg; i++) { | |
| 464 // These go above the volatile CPU registers. | |
| 465 const int slot = | |
| 466 (i - kDartFirstVolatileFpuReg) + kDartVolatileCpuRegCount + 2; | |
| 467 FRegister reg = static_cast<FRegister>(i); | |
| 468 swc1(reg, Address(SP, slot * kWordSize)); | |
| 469 } | |
| 470 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { | |
| 471 // + 2 because FP goes in slot 0. | |
| 472 const int slot = (i - kDartFirstVolatileCpuReg) + 2; | |
| 473 Register reg = static_cast<Register>(i); | |
| 474 sw(reg, Address(SP, slot * kWordSize)); | |
| 475 } | |
| 476 sw(RA, Address(SP, 1 * kWordSize)); | |
| 477 sw(FP, Address(SP, 0 * kWordSize)); | |
| 478 mov(FP, SP); | |
| 479 | |
| 480 ReserveAlignedFrameSpace(frame_space); | |
| 481 } | |
| 482 | |
| 483 | |
| 484 void Assembler::LeaveCallRuntimeFrame() { | |
| 485 const intptr_t kPushedRegistersSize = | |
| 486 kDartVolatileCpuRegCount * kWordSize + | |
| 487 2 * kWordSize + // FP and RA. | |
| 488 kDartVolatileFpuRegCount * kWordSize; | |
| 489 | |
| 490 // SP might have been modified to reserve space for arguments | |
| 491 // and ensure proper alignment of the stack frame. | |
| 492 // We need to restore it before restoring registers. | |
| 493 mov(SP, FP); | |
| 494 | |
| 495 // Restore volatile CPU and FPU registers from the stack. | |
| 496 lw(FP, Address(SP, 0 * kWordSize)); | |
| 497 lw(RA, Address(SP, 1 * kWordSize)); | |
| 498 for (int i = kDartFirstVolatileCpuReg; i <= kDartLastVolatileCpuReg; i++) { | |
| 499 // + 2 because FP goes in slot 0. | |
| 500 const int slot = (i - kDartFirstVolatileCpuReg) + 2; | |
| 501 Register reg = static_cast<Register>(i); | |
| 502 lw(reg, Address(SP, slot * kWordSize)); | |
| 503 } | |
| 504 for (int i = kDartFirstVolatileFpuReg; i <= kDartLastVolatileFpuReg; i++) { | |
| 505 // These go above the volatile CPU registers. | |
| 506 const int slot = | |
| 507 (i - kDartFirstVolatileFpuReg) + kDartVolatileCpuRegCount + 2; | |
| 508 FRegister reg = static_cast<FRegister>(i); | |
| 509 lwc1(reg, Address(SP, slot * kWordSize)); | |
| 510 } | |
| 511 addiu(SP, SP, Immediate(kPushedRegistersSize)); | |
| 512 } | |
| 513 | |
| 514 | |
| 363 int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { | 515 int32_t Assembler::AddExternalLabel(const ExternalLabel* label) { |
| 364 if (object_pool_.IsNull()) { | 516 if (object_pool_.IsNull()) { |
| 365 // The object pool cannot be used in the vm isolate. | 517 // The object pool cannot be used in the vm isolate. |
| 366 ASSERT(Isolate::Current() != Dart::vm_isolate()); | 518 ASSERT(Isolate::Current() != Dart::vm_isolate()); |
| 367 object_pool_ = GrowableObjectArray::New(Heap::kOld); | 519 object_pool_ = GrowableObjectArray::New(Heap::kOld); |
| 368 } | 520 } |
| 369 const word address = label->address(); | 521 const word address = label->address(); |
| 370 ASSERT(Utils::IsAligned(address, 4)); | 522 ASSERT(Utils::IsAligned(address, 4)); |
| 371 // The address is stored in the object array as a RawSmi. | 523 // The address is stored in the object array as a RawSmi. |
| 372 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); | 524 const Smi& smi = Smi::Handle(Smi::New(address >> kSmiTagShift)); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 385 b(&stop); | 537 b(&stop); |
| 386 Emit(reinterpret_cast<int32_t>(message)); | 538 Emit(reinterpret_cast<int32_t>(message)); |
| 387 Bind(&stop); | 539 Bind(&stop); |
| 388 break_(Instr::kStopMessageCode); | 540 break_(Instr::kStopMessageCode); |
| 389 } | 541 } |
| 390 | 542 |
| 391 } // namespace dart | 543 } // namespace dart |
| 392 | 544 |
| 393 #endif // defined TARGET_ARCH_MIPS | 545 #endif // defined TARGET_ARCH_MIPS |
| 394 | 546 |
| OLD | NEW |