| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 the V8 project authors. All rights reserved. |
| 2 // Redistribution and use in source and binary forms, with or without | 2 // Redistribution and use in source and binary forms, with or without |
| 3 // modification, are permitted provided that the following conditions are | 3 // modification, are permitted provided that the following conditions are |
| 4 // met: | 4 // met: |
| 5 // | 5 // |
| 6 // * Redistributions of source code must retain the above copyright | 6 // * Redistributions of source code must retain the above copyright |
| 7 // notice, this list of conditions and the following disclaimer. | 7 // notice, this list of conditions and the following disclaimer. |
| 8 // * Redistributions in binary form must reproduce the above | 8 // * Redistributions in binary form must reproduce the above |
| 9 // copyright notice, this list of conditions and the following | 9 // copyright notice, this list of conditions and the following |
| 10 // disclaimer in the documentation and/or other materials provided | 10 // disclaimer in the documentation and/or other materials provided |
| (...skipping 13 matching lines...) Expand all Loading... |
| 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | 24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 27 | 27 |
| 28 #include "v8.h" | 28 #include "v8.h" |
| 29 | 29 |
| 30 #include "mips/lithium-codegen-mips.h" | 30 #include "mips/lithium-codegen-mips.h" |
| 31 #include "mips/lithium-gap-resolver-mips.h" | 31 #include "mips/lithium-gap-resolver-mips.h" |
| 32 #include "code-stubs.h" | 32 #include "code-stubs.h" |
| 33 #include "stub-cache.h" | 33 #include "stub-cache.h" |
| 34 #include "hydrogen-osr.h" |
| 34 | 35 |
| 35 namespace v8 { | 36 namespace v8 { |
| 36 namespace internal { | 37 namespace internal { |
| 37 | 38 |
| 38 | 39 |
| 39 class SafepointGenerator V8_FINAL : public CallWrapper { | 40 class SafepointGenerator V8_FINAL : public CallWrapper { |
| 40 public: | 41 public: |
| 41 SafepointGenerator(LCodeGen* codegen, | 42 SafepointGenerator(LCodeGen* codegen, |
| 42 LPointerMap* pointers, | 43 LPointerMap* pointers, |
| 43 Safepoint::DeoptMode mode) | 44 Safepoint::DeoptMode mode) |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 240 } | 241 } |
| 241 | 242 |
| 242 // Trace the call. | 243 // Trace the call. |
| 243 if (FLAG_trace && info()->IsOptimizing()) { | 244 if (FLAG_trace && info()->IsOptimizing()) { |
| 244 __ CallRuntime(Runtime::kTraceEnter, 0); | 245 __ CallRuntime(Runtime::kTraceEnter, 0); |
| 245 } | 246 } |
| 246 return !is_aborted(); | 247 return !is_aborted(); |
| 247 } | 248 } |
| 248 | 249 |
| 249 | 250 |
| 251 void LCodeGen::GenerateOsrPrologue() { |
| 252 // Generate the OSR entry prologue at the first unknown OSR value, or if there |
| 253 // are none, at the OSR entrypoint instruction. |
| 254 if (osr_pc_offset_ >= 0) return; |
| 255 |
| 256 osr_pc_offset_ = masm()->pc_offset(); |
| 257 |
| 258 // Adjust the frame size, subsuming the unoptimized frame into the |
| 259 // optimized frame. |
| 260 int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); |
| 261 ASSERT(slots >= 0); |
| 262 __ Subu(sp, sp, Operand(slots * kPointerSize)); |
| 263 } |
| 264 |
| 265 |
| 250 bool LCodeGen::GenerateBody() { | 266 bool LCodeGen::GenerateBody() { |
| 251 ASSERT(is_generating()); | 267 ASSERT(is_generating()); |
| 252 bool emit_instructions = true; | 268 bool emit_instructions = true; |
| 253 for (current_instruction_ = 0; | 269 for (current_instruction_ = 0; |
| 254 !is_aborted() && current_instruction_ < instructions_->length(); | 270 !is_aborted() && current_instruction_ < instructions_->length(); |
| 255 current_instruction_++) { | 271 current_instruction_++) { |
| 256 LInstruction* instr = instructions_->at(current_instruction_); | 272 LInstruction* instr = instructions_->at(current_instruction_); |
| 257 | 273 |
| 258 // Don't emit code for basic blocks with a replacement. | 274 // Don't emit code for basic blocks with a replacement. |
| 259 if (instr->IsLabel()) { | 275 if (instr->IsLabel()) { |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 391 return ToRegister(op->index()); | 407 return ToRegister(op->index()); |
| 392 } | 408 } |
| 393 | 409 |
| 394 | 410 |
| 395 Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) { | 411 Register LCodeGen::EmitLoadRegister(LOperand* op, Register scratch) { |
| 396 if (op->IsRegister()) { | 412 if (op->IsRegister()) { |
| 397 return ToRegister(op->index()); | 413 return ToRegister(op->index()); |
| 398 } else if (op->IsConstantOperand()) { | 414 } else if (op->IsConstantOperand()) { |
| 399 LConstantOperand* const_op = LConstantOperand::cast(op); | 415 LConstantOperand* const_op = LConstantOperand::cast(op); |
| 400 HConstant* constant = chunk_->LookupConstant(const_op); | 416 HConstant* constant = chunk_->LookupConstant(const_op); |
| 401 Handle<Object> literal = constant->handle(); | 417 Handle<Object> literal = constant->handle(isolate()); |
| 402 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 418 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
| 403 if (r.IsInteger32()) { | 419 if (r.IsInteger32()) { |
| 404 ASSERT(literal->IsNumber()); | 420 ASSERT(literal->IsNumber()); |
| 405 __ li(scratch, Operand(static_cast<int32_t>(literal->Number()))); | 421 __ li(scratch, Operand(static_cast<int32_t>(literal->Number()))); |
| 406 } else if (r.IsSmi()) { | 422 } else if (r.IsSmi()) { |
| 407 ASSERT(constant->HasSmiValue()); | 423 ASSERT(constant->HasSmiValue()); |
| 408 __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value()))); | 424 __ li(scratch, Operand(Smi::FromInt(constant->Integer32Value()))); |
| 409 } else if (r.IsDouble()) { | 425 } else if (r.IsDouble()) { |
| 410 Abort(kEmitLoadRegisterUnsupportedDoubleImmediate); | 426 Abort(kEmitLoadRegisterUnsupportedDoubleImmediate); |
| 411 } else { | 427 } else { |
| (...skipping 17 matching lines...) Expand all Loading... |
| 429 | 445 |
| 430 | 446 |
| 431 DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, | 447 DoubleRegister LCodeGen::EmitLoadDoubleRegister(LOperand* op, |
| 432 FloatRegister flt_scratch, | 448 FloatRegister flt_scratch, |
| 433 DoubleRegister dbl_scratch) { | 449 DoubleRegister dbl_scratch) { |
| 434 if (op->IsDoubleRegister()) { | 450 if (op->IsDoubleRegister()) { |
| 435 return ToDoubleRegister(op->index()); | 451 return ToDoubleRegister(op->index()); |
| 436 } else if (op->IsConstantOperand()) { | 452 } else if (op->IsConstantOperand()) { |
| 437 LConstantOperand* const_op = LConstantOperand::cast(op); | 453 LConstantOperand* const_op = LConstantOperand::cast(op); |
| 438 HConstant* constant = chunk_->LookupConstant(const_op); | 454 HConstant* constant = chunk_->LookupConstant(const_op); |
| 439 Handle<Object> literal = constant->handle(); | 455 Handle<Object> literal = constant->handle(isolate()); |
| 440 Representation r = chunk_->LookupLiteralRepresentation(const_op); | 456 Representation r = chunk_->LookupLiteralRepresentation(const_op); |
| 441 if (r.IsInteger32()) { | 457 if (r.IsInteger32()) { |
| 442 ASSERT(literal->IsNumber()); | 458 ASSERT(literal->IsNumber()); |
| 443 __ li(at, Operand(static_cast<int32_t>(literal->Number()))); | 459 __ li(at, Operand(static_cast<int32_t>(literal->Number()))); |
| 444 __ mtc1(at, flt_scratch); | 460 __ mtc1(at, flt_scratch); |
| 445 __ cvt_d_w(dbl_scratch, flt_scratch); | 461 __ cvt_d_w(dbl_scratch, flt_scratch); |
| 446 return dbl_scratch; | 462 return dbl_scratch; |
| 447 } else if (r.IsDouble()) { | 463 } else if (r.IsDouble()) { |
| 448 Abort(kUnsupportedDoubleImmediate); | 464 Abort(kUnsupportedDoubleImmediate); |
| 449 } else if (r.IsTagged()) { | 465 } else if (r.IsTagged()) { |
| 450 Abort(kUnsupportedTaggedImmediate); | 466 Abort(kUnsupportedTaggedImmediate); |
| 451 } | 467 } |
| 452 } else if (op->IsStackSlot() || op->IsArgument()) { | 468 } else if (op->IsStackSlot() || op->IsArgument()) { |
| 453 MemOperand mem_op = ToMemOperand(op); | 469 MemOperand mem_op = ToMemOperand(op); |
| 454 __ ldc1(dbl_scratch, mem_op); | 470 __ ldc1(dbl_scratch, mem_op); |
| 455 return dbl_scratch; | 471 return dbl_scratch; |
| 456 } | 472 } |
| 457 UNREACHABLE(); | 473 UNREACHABLE(); |
| 458 return dbl_scratch; | 474 return dbl_scratch; |
| 459 } | 475 } |
| 460 | 476 |
| 461 | 477 |
| 462 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { | 478 Handle<Object> LCodeGen::ToHandle(LConstantOperand* op) const { |
| 463 HConstant* constant = chunk_->LookupConstant(op); | 479 HConstant* constant = chunk_->LookupConstant(op); |
| 464 ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); | 480 ASSERT(chunk_->LookupLiteralRepresentation(op).IsSmiOrTagged()); |
| 465 return constant->handle(); | 481 return constant->handle(isolate()); |
| 466 } | 482 } |
| 467 | 483 |
| 468 | 484 |
| 469 bool LCodeGen::IsInteger32(LConstantOperand* op) const { | 485 bool LCodeGen::IsInteger32(LConstantOperand* op) const { |
| 470 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); | 486 return chunk_->LookupLiteralRepresentation(op).IsSmiOrInteger32(); |
| 471 } | 487 } |
| 472 | 488 |
| 473 | 489 |
| 474 bool LCodeGen::IsSmi(LConstantOperand* op) const { | 490 bool LCodeGen::IsSmi(LConstantOperand* op) const { |
| 475 return chunk_->LookupLiteralRepresentation(op).IsSmi(); | 491 return chunk_->LookupLiteralRepresentation(op).IsSmi(); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 512 if (r.IsSmi()) { | 528 if (r.IsSmi()) { |
| 513 ASSERT(constant->HasSmiValue()); | 529 ASSERT(constant->HasSmiValue()); |
| 514 return Operand(Smi::FromInt(constant->Integer32Value())); | 530 return Operand(Smi::FromInt(constant->Integer32Value())); |
| 515 } else if (r.IsInteger32()) { | 531 } else if (r.IsInteger32()) { |
| 516 ASSERT(constant->HasInteger32Value()); | 532 ASSERT(constant->HasInteger32Value()); |
| 517 return Operand(constant->Integer32Value()); | 533 return Operand(constant->Integer32Value()); |
| 518 } else if (r.IsDouble()) { | 534 } else if (r.IsDouble()) { |
| 519 Abort(kToOperandUnsupportedDoubleImmediate); | 535 Abort(kToOperandUnsupportedDoubleImmediate); |
| 520 } | 536 } |
| 521 ASSERT(r.IsTagged()); | 537 ASSERT(r.IsTagged()); |
| 522 return Operand(constant->handle()); | 538 return Operand(constant->handle(isolate())); |
| 523 } else if (op->IsRegister()) { | 539 } else if (op->IsRegister()) { |
| 524 return Operand(ToRegister(op)); | 540 return Operand(ToRegister(op)); |
| 525 } else if (op->IsDoubleRegister()) { | 541 } else if (op->IsDoubleRegister()) { |
| 526 Abort(kToOperandIsDoubleRegisterUnimplemented); | 542 Abort(kToOperandIsDoubleRegisterUnimplemented); |
| 527 return Operand(0); | 543 return Operand(0); |
| 528 } | 544 } |
| 529 // Stack slots not implemented, use ToMemOperand instead. | 545 // Stack slots not implemented, use ToMemOperand instead. |
| 530 UNREACHABLE(); | 546 UNREACHABLE(); |
| 531 return Operand(0); | 547 return Operand(0); |
| 532 } | 548 } |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 659 } else if (is_uint32) { | 675 } else if (is_uint32) { |
| 660 translation->StoreUint32Register(reg); | 676 translation->StoreUint32Register(reg); |
| 661 } else { | 677 } else { |
| 662 translation->StoreInt32Register(reg); | 678 translation->StoreInt32Register(reg); |
| 663 } | 679 } |
| 664 } else if (op->IsDoubleRegister()) { | 680 } else if (op->IsDoubleRegister()) { |
| 665 DoubleRegister reg = ToDoubleRegister(op); | 681 DoubleRegister reg = ToDoubleRegister(op); |
| 666 translation->StoreDoubleRegister(reg); | 682 translation->StoreDoubleRegister(reg); |
| 667 } else if (op->IsConstantOperand()) { | 683 } else if (op->IsConstantOperand()) { |
| 668 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); | 684 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); |
| 669 int src_index = DefineDeoptimizationLiteral(constant->handle()); | 685 int src_index = DefineDeoptimizationLiteral(constant->handle(isolate())); |
| 670 translation->StoreLiteral(src_index); | 686 translation->StoreLiteral(src_index); |
| 671 } else { | 687 } else { |
| 672 UNREACHABLE(); | 688 UNREACHABLE(); |
| 673 } | 689 } |
| 674 } | 690 } |
| 675 | 691 |
| 676 | 692 |
| 677 void LCodeGen::CallCode(Handle<Code> code, | 693 void LCodeGen::CallCode(Handle<Code> code, |
| 678 RelocInfo::Mode mode, | 694 RelocInfo::Mode mode, |
| 679 LInstruction* instr) { | 695 LInstruction* instr) { |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1064 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1080 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); |
| 1065 break; | 1081 break; |
| 1066 } | 1082 } |
| 1067 default: | 1083 default: |
| 1068 UNREACHABLE(); | 1084 UNREACHABLE(); |
| 1069 } | 1085 } |
| 1070 } | 1086 } |
| 1071 | 1087 |
| 1072 | 1088 |
| 1073 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1089 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
| 1074 // Record the address of the first unknown OSR value as the place to enter. | 1090 GenerateOsrPrologue(); |
| 1075 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset(); | |
| 1076 } | 1091 } |
| 1077 | 1092 |
| 1078 | 1093 |
| 1079 void LCodeGen::DoModI(LModI* instr) { | 1094 void LCodeGen::DoModI(LModI* instr) { |
| 1080 HMod* hmod = instr->hydrogen(); | 1095 HMod* hmod = instr->hydrogen(); |
| 1081 HValue* left = hmod->left(); | 1096 HValue* left = hmod->left(); |
| 1082 HValue* right = hmod->right(); | 1097 HValue* right = hmod->right(); |
| 1083 if (hmod->HasPowerOf2Divisor()) { | 1098 if (hmod->HasPowerOf2Divisor()) { |
| 1084 const Register left_reg = ToRegister(instr->left()); | 1099 const Register left_reg = ToRegister(instr->left()); |
| 1085 const Register result_reg = ToRegister(instr->result()); | 1100 const Register result_reg = ToRegister(instr->result()); |
| (...skipping 593 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1679 __ Move(result, v); | 1694 __ Move(result, v); |
| 1680 } | 1695 } |
| 1681 | 1696 |
| 1682 | 1697 |
| 1683 void LCodeGen::DoConstantE(LConstantE* instr) { | 1698 void LCodeGen::DoConstantE(LConstantE* instr) { |
| 1684 __ li(ToRegister(instr->result()), Operand(instr->value())); | 1699 __ li(ToRegister(instr->result()), Operand(instr->value())); |
| 1685 } | 1700 } |
| 1686 | 1701 |
| 1687 | 1702 |
| 1688 void LCodeGen::DoConstantT(LConstantT* instr) { | 1703 void LCodeGen::DoConstantT(LConstantT* instr) { |
| 1689 Handle<Object> value = instr->value(); | 1704 Handle<Object> value = instr->value(isolate()); |
| 1690 AllowDeferredHandleDereference smi_check; | 1705 AllowDeferredHandleDereference smi_check; |
| 1691 __ LoadObject(ToRegister(instr->result()), value); | 1706 __ LoadObject(ToRegister(instr->result()), value); |
| 1692 } | 1707 } |
| 1693 | 1708 |
| 1694 | 1709 |
| 1695 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { | 1710 void LCodeGen::DoMapEnumLength(LMapEnumLength* instr) { |
| 1696 Register result = ToRegister(instr->result()); | 1711 Register result = ToRegister(instr->result()); |
| 1697 Register map = ToRegister(instr->value()); | 1712 Register map = ToRegister(instr->value()); |
| 1698 __ EnumLength(result, map); | 1713 __ EnumLength(result, map); |
| 1699 } | 1714 } |
| (...skipping 3974 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5674 // This is a pseudo-instruction that ensures that the environment here is | 5689 // This is a pseudo-instruction that ensures that the environment here is |
| 5675 // properly registered for deoptimization and records the assembler's PC | 5690 // properly registered for deoptimization and records the assembler's PC |
| 5676 // offset. | 5691 // offset. |
| 5677 LEnvironment* environment = instr->environment(); | 5692 LEnvironment* environment = instr->environment(); |
| 5678 | 5693 |
| 5679 // If the environment were already registered, we would have no way of | 5694 // If the environment were already registered, we would have no way of |
| 5680 // backpatching it with the spill slot operands. | 5695 // backpatching it with the spill slot operands. |
| 5681 ASSERT(!environment->HasBeenRegistered()); | 5696 ASSERT(!environment->HasBeenRegistered()); |
| 5682 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); | 5697 RegisterEnvironmentForDeoptimization(environment, Safepoint::kNoLazyDeopt); |
| 5683 | 5698 |
| 5684 // Normally we record the first unknown OSR value as the entrypoint to the OSR | 5699 GenerateOsrPrologue(); |
| 5685 // code, but if there were none, record the entrypoint here. | |
| 5686 if (osr_pc_offset_ == -1) osr_pc_offset_ = masm()->pc_offset(); | |
| 5687 } | 5700 } |
| 5688 | 5701 |
| 5689 | 5702 |
| 5690 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { | 5703 void LCodeGen::DoForInPrepareMap(LForInPrepareMap* instr) { |
| 5691 Register result = ToRegister(instr->result()); | 5704 Register result = ToRegister(instr->result()); |
| 5692 Register object = ToRegister(instr->object()); | 5705 Register object = ToRegister(instr->object()); |
| 5693 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); | 5706 __ LoadRoot(at, Heap::kUndefinedValueRootIndex); |
| 5694 DeoptimizeIf(eq, instr->environment(), object, Operand(at)); | 5707 DeoptimizeIf(eq, instr->environment(), object, Operand(at)); |
| 5695 | 5708 |
| 5696 Register null_value = t1; | 5709 Register null_value = t1; |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5775 __ Subu(scratch, result, scratch); | 5788 __ Subu(scratch, result, scratch); |
| 5776 __ lw(result, FieldMemOperand(scratch, | 5789 __ lw(result, FieldMemOperand(scratch, |
| 5777 FixedArray::kHeaderSize - kPointerSize)); | 5790 FixedArray::kHeaderSize - kPointerSize)); |
| 5778 __ bind(&done); | 5791 __ bind(&done); |
| 5779 } | 5792 } |
| 5780 | 5793 |
| 5781 | 5794 |
| 5782 #undef __ | 5795 #undef __ |
| 5783 | 5796 |
| 5784 } } // namespace v8::internal | 5797 } } // namespace v8::internal |
| OLD | NEW |