| 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 80 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 91   info()->CommitDependencies(code); | 91   info()->CommitDependencies(code); | 
| 92 } | 92 } | 
| 93 | 93 | 
| 94 | 94 | 
| 95 void LCodeGen::Abort(BailoutReason reason) { | 95 void LCodeGen::Abort(BailoutReason reason) { | 
| 96   info()->set_bailout_reason(reason); | 96   info()->set_bailout_reason(reason); | 
| 97   status_ = ABORTED; | 97   status_ = ABORTED; | 
| 98 } | 98 } | 
| 99 | 99 | 
| 100 | 100 | 
| 101 void LCodeGen::Comment(const char* format, ...) { |  | 
| 102   if (!FLAG_code_comments) return; |  | 
| 103   char buffer[4 * KB]; |  | 
| 104   StringBuilder builder(buffer, ARRAY_SIZE(buffer)); |  | 
| 105   va_list arguments; |  | 
| 106   va_start(arguments, format); |  | 
| 107   builder.AddFormattedList(format, arguments); |  | 
| 108   va_end(arguments); |  | 
| 109 |  | 
| 110   // Copy the string before recording it in the assembler to avoid |  | 
| 111   // issues when the stack allocated buffer goes out of scope. |  | 
| 112   size_t length = builder.position(); |  | 
| 113   Vector<char> copy = Vector<char>::New(length + 1); |  | 
| 114   OS::MemCopy(copy.start(), builder.Finalize(), copy.length()); |  | 
| 115   masm()->RecordComment(copy.start()); |  | 
| 116 } |  | 
| 117 |  | 
| 118 |  | 
| 119 bool LCodeGen::GeneratePrologue() { | 101 bool LCodeGen::GeneratePrologue() { | 
| 120   ASSERT(is_generating()); | 102   ASSERT(is_generating()); | 
| 121 | 103 | 
| 122   if (info()->IsOptimizing()) { | 104   if (info()->IsOptimizing()) { | 
| 123     ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 105     ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 
| 124 | 106 | 
| 125 #ifdef DEBUG | 107 #ifdef DEBUG | 
| 126     if (strlen(FLAG_stop_at) > 0 && | 108     if (strlen(FLAG_stop_at) > 0 && | 
| 127         info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 109         info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 
| 128       __ stop("stop_at"); | 110       __ stop("stop_at"); | 
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 264   osr_pc_offset_ = masm()->pc_offset(); | 246   osr_pc_offset_ = masm()->pc_offset(); | 
| 265 | 247 | 
| 266   // Adjust the frame size, subsuming the unoptimized frame into the | 248   // Adjust the frame size, subsuming the unoptimized frame into the | 
| 267   // optimized frame. | 249   // optimized frame. | 
| 268   int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); | 250   int slots = GetStackSlotCount() - graph()->osr()->UnoptimizedFrameSlots(); | 
| 269   ASSERT(slots >= 0); | 251   ASSERT(slots >= 0); | 
| 270   __ sub(sp, sp, Operand(slots * kPointerSize)); | 252   __ sub(sp, sp, Operand(slots * kPointerSize)); | 
| 271 } | 253 } | 
| 272 | 254 | 
| 273 | 255 | 
| 274 bool LCodeGen::GenerateBody() { |  | 
| 275   ASSERT(is_generating()); |  | 
| 276   bool emit_instructions = true; |  | 
| 277   for (current_instruction_ = 0; |  | 
| 278        !is_aborted() && current_instruction_ < instructions_->length(); |  | 
| 279        current_instruction_++) { |  | 
| 280     LInstruction* instr = instructions_->at(current_instruction_); |  | 
| 281 |  | 
| 282     // Don't emit code for basic blocks with a replacement. |  | 
| 283     if (instr->IsLabel()) { |  | 
| 284       emit_instructions = !LLabel::cast(instr)->HasReplacement(); |  | 
| 285     } |  | 
| 286     if (!emit_instructions) continue; |  | 
| 287 |  | 
| 288     if (FLAG_code_comments && instr->HasInterestingComment(this)) { |  | 
| 289       Comment(";;; <@%d,#%d> %s", |  | 
| 290               current_instruction_, |  | 
| 291               instr->hydrogen_value()->id(), |  | 
| 292               instr->Mnemonic()); |  | 
| 293     } |  | 
| 294 |  | 
| 295     RecordAndUpdatePosition(instr->position()); |  | 
| 296 |  | 
| 297     instr->CompileToNative(this); |  | 
| 298   } |  | 
| 299   EnsureSpaceForLazyDeopt(); |  | 
| 300   last_lazy_deopt_pc_ = masm()->pc_offset(); |  | 
| 301   return !is_aborted(); |  | 
| 302 } |  | 
| 303 |  | 
| 304 |  | 
| 305 bool LCodeGen::GenerateDeferredCode() { | 256 bool LCodeGen::GenerateDeferredCode() { | 
| 306   ASSERT(is_generating()); | 257   ASSERT(is_generating()); | 
| 307   if (deferred_.length() > 0) { | 258   if (deferred_.length() > 0) { | 
| 308     for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 259     for (int i = 0; !is_aborted() && i < deferred_.length(); i++) { | 
| 309       LDeferredCode* code = deferred_[i]; | 260       LDeferredCode* code = deferred_[i]; | 
| 310 | 261 | 
| 311       int pos = instructions_->at(code->instruction_index())->position(); | 262       int pos = instructions_->at(code->instruction_index())->position(); | 
| 312       RecordAndUpdatePosition(pos); | 263       RecordAndUpdatePosition(pos); | 
| 313 | 264 | 
| 314       Comment(";;; <@%d,#%d> " | 265       Comment(";;; <@%d,#%d> " | 
| (...skipping 407 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 722                         TargetAddressStorageMode storage_mode) { | 673                         TargetAddressStorageMode storage_mode) { | 
| 723   CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, storage_mode); | 674   CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, storage_mode); | 
| 724 } | 675 } | 
| 725 | 676 | 
| 726 | 677 | 
| 727 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 678 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 
| 728                                RelocInfo::Mode mode, | 679                                RelocInfo::Mode mode, | 
| 729                                LInstruction* instr, | 680                                LInstruction* instr, | 
| 730                                SafepointMode safepoint_mode, | 681                                SafepointMode safepoint_mode, | 
| 731                                TargetAddressStorageMode storage_mode) { | 682                                TargetAddressStorageMode storage_mode) { | 
| 732   EnsureSpaceForLazyDeopt(); | 683   EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 
| 733   ASSERT(instr != NULL); | 684   ASSERT(instr != NULL); | 
| 734   // Block literal pool emission to ensure nop indicating no inlined smi code | 685   // Block literal pool emission to ensure nop indicating no inlined smi code | 
| 735   // is in the correct position. | 686   // is in the correct position. | 
| 736   Assembler::BlockConstPoolScope block_const_pool(masm()); | 687   Assembler::BlockConstPoolScope block_const_pool(masm()); | 
| 737   LPointerMap* pointers = instr->pointer_map(); | 688   LPointerMap* pointers = instr->pointer_map(); | 
| 738   RecordPosition(pointers->position()); | 689   RecordPosition(pointers->position()); | 
| 739   __ Call(code, mode, TypeFeedbackId::None(), al, storage_mode); | 690   __ Call(code, mode, TypeFeedbackId::None(), al, storage_mode); | 
| 740   RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 691   RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 
| 741 | 692 | 
| 742   // Signal that we don't inline smi code before these stubs in the | 693   // Signal that we don't inline smi code before these stubs in the | 
| (...skipping 1443 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 2186 | 2137 | 
| 2187   BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 2138   BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 
| 2188   // Block literal pool emission to ensure nop indicating no inlined smi code | 2139   // Block literal pool emission to ensure nop indicating no inlined smi code | 
| 2189   // is in the correct position. | 2140   // is in the correct position. | 
| 2190   Assembler::BlockConstPoolScope block_const_pool(masm()); | 2141   Assembler::BlockConstPoolScope block_const_pool(masm()); | 
| 2191   CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2142   CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 
| 2192   __ nop();  // Signals no inlined code. | 2143   __ nop();  // Signals no inlined code. | 
| 2193 } | 2144 } | 
| 2194 | 2145 | 
| 2195 | 2146 | 
| 2196 int LCodeGen::GetNextEmittedBlock() const { |  | 
| 2197   for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |  | 
| 2198     if (!chunk_->GetLabel(i)->HasReplacement()) return i; |  | 
| 2199   } |  | 
| 2200   return -1; |  | 
| 2201 } |  | 
| 2202 |  | 
| 2203 template<class InstrType> | 2147 template<class InstrType> | 
| 2204 void LCodeGen::EmitBranch(InstrType instr, Condition condition) { | 2148 void LCodeGen::EmitBranch(InstrType instr, Condition condition) { | 
| 2205   int left_block = instr->TrueDestination(chunk_); | 2149   int left_block = instr->TrueDestination(chunk_); | 
| 2206   int right_block = instr->FalseDestination(chunk_); | 2150   int right_block = instr->FalseDestination(chunk_); | 
| 2207 | 2151 | 
| 2208   int next_block = GetNextEmittedBlock(); | 2152   int next_block = GetNextEmittedBlock(); | 
| 2209 | 2153 | 
| 2210   if (right_block == left_block || condition == al) { | 2154   if (right_block == left_block || condition == al) { | 
| 2211     EmitGoto(left_block); | 2155     EmitGoto(left_block); | 
| 2212   } else if (left_block == next_block) { | 2156   } else if (left_block == next_block) { | 
| (...skipping 3422 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5635   __ b(ne, &check_frame_marker); | 5579   __ b(ne, &check_frame_marker); | 
| 5636   __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); | 5580   __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kCallerFPOffset)); | 
| 5637 | 5581 | 
| 5638   // Check the marker in the calling frame. | 5582   // Check the marker in the calling frame. | 
| 5639   __ bind(&check_frame_marker); | 5583   __ bind(&check_frame_marker); | 
| 5640   __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); | 5584   __ ldr(temp1, MemOperand(temp1, StandardFrameConstants::kMarkerOffset)); | 
| 5641   __ cmp(temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 5585   __ cmp(temp1, Operand(Smi::FromInt(StackFrame::CONSTRUCT))); | 
| 5642 } | 5586 } | 
| 5643 | 5587 | 
| 5644 | 5588 | 
| 5645 void LCodeGen::EnsureSpaceForLazyDeopt() { | 5589 void LCodeGen::EnsureSpaceForLazyDeopt(int space_needed) { | 
| 5646   if (info()->IsStub()) return; | 5590   if (info()->IsStub()) return; | 
| 5647   // Ensure that we have enough space after the previous lazy-bailout | 5591   // Ensure that we have enough space after the previous lazy-bailout | 
| 5648   // instruction for patching the code here. | 5592   // instruction for patching the code here. | 
| 5649   int current_pc = masm()->pc_offset(); | 5593   int current_pc = masm()->pc_offset(); | 
| 5650   int patch_size = Deoptimizer::patch_size(); | 5594   if (current_pc < last_lazy_deopt_pc_ + space_needed) { | 
| 5651   if (current_pc < last_lazy_deopt_pc_ + patch_size) { |  | 
| 5652     // Block literal pool emission for duration of padding. | 5595     // Block literal pool emission for duration of padding. | 
| 5653     Assembler::BlockConstPoolScope block_const_pool(masm()); | 5596     Assembler::BlockConstPoolScope block_const_pool(masm()); | 
| 5654     int padding_size = last_lazy_deopt_pc_ + patch_size - current_pc; | 5597     int padding_size = last_lazy_deopt_pc_ + space_needed - current_pc; | 
| 5655     ASSERT_EQ(0, padding_size % Assembler::kInstrSize); | 5598     ASSERT_EQ(0, padding_size % Assembler::kInstrSize); | 
| 5656     while (padding_size > 0) { | 5599     while (padding_size > 0) { | 
| 5657       __ nop(); | 5600       __ nop(); | 
| 5658       padding_size -= Assembler::kInstrSize; | 5601       padding_size -= Assembler::kInstrSize; | 
| 5659     } | 5602     } | 
| 5660   } | 5603   } | 
| 5661 } | 5604 } | 
| 5662 | 5605 | 
| 5663 | 5606 | 
| 5664 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 5607 void LCodeGen::DoLazyBailout(LLazyBailout* instr) { | 
| 5665   EnsureSpaceForLazyDeopt(); | 5608   EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 
| 5666   last_lazy_deopt_pc_ = masm()->pc_offset(); | 5609   last_lazy_deopt_pc_ = masm()->pc_offset(); | 
| 5667   ASSERT(instr->HasEnvironment()); | 5610   ASSERT(instr->HasEnvironment()); | 
| 5668   LEnvironment* env = instr->environment(); | 5611   LEnvironment* env = instr->environment(); | 
| 5669   RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5612   RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 
| 5670   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5613   safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 
| 5671 } | 5614 } | 
| 5672 | 5615 | 
| 5673 | 5616 | 
| 5674 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 5617 void LCodeGen::DoDeoptimize(LDeoptimize* instr) { | 
| 5675   Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 5618   Deoptimizer::BailoutType type = instr->hydrogen()->type(); | 
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5725     Label done; | 5668     Label done; | 
| 5726     __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 5669     __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 
| 5727     __ cmp(sp, Operand(ip)); | 5670     __ cmp(sp, Operand(ip)); | 
| 5728     __ b(hs, &done); | 5671     __ b(hs, &done); | 
| 5729     PredictableCodeSizeScope predictable(masm_, 2 * Assembler::kInstrSize); | 5672     PredictableCodeSizeScope predictable(masm_, 2 * Assembler::kInstrSize); | 
| 5730     ASSERT(instr->context()->IsRegister()); | 5673     ASSERT(instr->context()->IsRegister()); | 
| 5731     ASSERT(ToRegister(instr->context()).is(cp)); | 5674     ASSERT(ToRegister(instr->context()).is(cp)); | 
| 5732     CallCode(isolate()->builtins()->StackCheck(), | 5675     CallCode(isolate()->builtins()->StackCheck(), | 
| 5733               RelocInfo::CODE_TARGET, | 5676               RelocInfo::CODE_TARGET, | 
| 5734               instr); | 5677               instr); | 
| 5735     EnsureSpaceForLazyDeopt(); | 5678     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 
| 5736     last_lazy_deopt_pc_ = masm()->pc_offset(); | 5679     last_lazy_deopt_pc_ = masm()->pc_offset(); | 
| 5737     __ bind(&done); | 5680     __ bind(&done); | 
| 5738     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5681     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 
| 5739     safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5682     safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 
| 5740   } else { | 5683   } else { | 
| 5741     ASSERT(instr->hydrogen()->is_backwards_branch()); | 5684     ASSERT(instr->hydrogen()->is_backwards_branch()); | 
| 5742     // Perform stack overflow check if this goto needs it before jumping. | 5685     // Perform stack overflow check if this goto needs it before jumping. | 
| 5743     DeferredStackCheck* deferred_stack_check = | 5686     DeferredStackCheck* deferred_stack_check = | 
| 5744         new(zone()) DeferredStackCheck(this, instr); | 5687         new(zone()) DeferredStackCheck(this, instr); | 
| 5745     __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 5688     __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 
| 5746     __ cmp(sp, Operand(ip)); | 5689     __ cmp(sp, Operand(ip)); | 
| 5747     __ b(lo, deferred_stack_check->entry()); | 5690     __ b(lo, deferred_stack_check->entry()); | 
| 5748     EnsureSpaceForLazyDeopt(); | 5691     EnsureSpaceForLazyDeopt(Deoptimizer::patch_size()); | 
| 5749     last_lazy_deopt_pc_ = masm()->pc_offset(); | 5692     last_lazy_deopt_pc_ = masm()->pc_offset(); | 
| 5750     __ bind(instr->done_label()); | 5693     __ bind(instr->done_label()); | 
| 5751     deferred_stack_check->SetExit(instr->done_label()); | 5694     deferred_stack_check->SetExit(instr->done_label()); | 
| 5752     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5695     RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 
| 5753     // Don't record a deoptimization index for the safepoint here. | 5696     // Don't record a deoptimization index for the safepoint here. | 
| 5754     // This will be done explicitly when emitting call and the safepoint in | 5697     // This will be done explicitly when emitting call and the safepoint in | 
| 5755     // the deferred code. | 5698     // the deferred code. | 
| 5756   } | 5699   } | 
| 5757 } | 5700 } | 
| 5758 | 5701 | 
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 5862   __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5805   __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 
| 5863   __ ldr(result, FieldMemOperand(scratch, | 5806   __ ldr(result, FieldMemOperand(scratch, | 
| 5864                                  FixedArray::kHeaderSize - kPointerSize)); | 5807                                  FixedArray::kHeaderSize - kPointerSize)); | 
| 5865   __ bind(&done); | 5808   __ bind(&done); | 
| 5866 } | 5809 } | 
| 5867 | 5810 | 
| 5868 | 5811 | 
| 5869 #undef __ | 5812 #undef __ | 
| 5870 | 5813 | 
| 5871 } }  // namespace v8::internal | 5814 } }  // namespace v8::internal | 
| OLD | NEW | 
|---|