| 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 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 | 109 |
| 110 // Copy the string before recording it in the assembler to avoid | 110 // Copy the string before recording it in the assembler to avoid |
| 111 // issues when the stack allocated buffer goes out of scope. | 111 // issues when the stack allocated buffer goes out of scope. |
| 112 size_t length = builder.position(); | 112 size_t length = builder.position(); |
| 113 Vector<char> copy = Vector<char>::New(length + 1); | 113 Vector<char> copy = Vector<char>::New(length + 1); |
| 114 OS::MemCopy(copy.start(), builder.Finalize(), copy.length()); | 114 OS::MemCopy(copy.start(), builder.Finalize(), copy.length()); |
| 115 masm()->RecordComment(copy.start()); | 115 masm()->RecordComment(copy.start()); |
| 116 } | 116 } |
| 117 | 117 |
| 118 | 118 |
| 119 void LCodeGen::SaveCallerDoubles() { |
| 120 ASSERT(info()->saves_caller_doubles()); |
| 121 ASSERT(NeedsEagerFrame()); |
| 122 Comment(";;; Save clobbered callee double registers"); |
| 123 int count = 0; |
| 124 BitVector* doubles = chunk()->allocated_double_registers(); |
| 125 BitVector::Iterator save_iterator(doubles); |
| 126 while (!save_iterator.Done()) { |
| 127 __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
| 128 MemOperand(sp, count * kDoubleSize)); |
| 129 save_iterator.Advance(); |
| 130 count++; |
| 131 } |
| 132 } |
| 133 |
| 134 |
| 135 void LCodeGen::RestoreCallerDoubles() { |
| 136 ASSERT(info()->saves_caller_doubles()); |
| 137 ASSERT(NeedsEagerFrame()); |
| 138 Comment(";;; Restore clobbered callee double registers"); |
| 139 BitVector* doubles = chunk()->allocated_double_registers(); |
| 140 BitVector::Iterator save_iterator(doubles); |
| 141 int count = 0; |
| 142 while (!save_iterator.Done()) { |
| 143 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
| 144 MemOperand(sp, count * kDoubleSize)); |
| 145 save_iterator.Advance(); |
| 146 count++; |
| 147 } |
| 148 } |
| 149 |
| 150 |
| 119 bool LCodeGen::GeneratePrologue() { | 151 bool LCodeGen::GeneratePrologue() { |
| 120 ASSERT(is_generating()); | 152 ASSERT(is_generating()); |
| 121 | 153 |
| 122 if (info()->IsOptimizing()) { | 154 if (info()->IsOptimizing()) { |
| 123 ProfileEntryHookStub::MaybeCallEntryHook(masm_); | 155 ProfileEntryHookStub::MaybeCallEntryHook(masm_); |
| 124 | 156 |
| 125 #ifdef DEBUG | 157 #ifdef DEBUG |
| 126 if (strlen(FLAG_stop_at) > 0 && | 158 if (strlen(FLAG_stop_at) > 0 && |
| 127 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { | 159 info_->function()->name()->IsUtf8EqualTo(CStrVector(FLAG_stop_at))) { |
| 128 __ stop("stop_at"); | 160 __ stop("stop_at"); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 186 __ cmp(r0, sp); | 218 __ cmp(r0, sp); |
| 187 __ b(ne, &loop); | 219 __ b(ne, &loop); |
| 188 __ pop(r1); | 220 __ pop(r1); |
| 189 __ pop(r0); | 221 __ pop(r0); |
| 190 } else { | 222 } else { |
| 191 __ sub(sp, sp, Operand(slots * kPointerSize)); | 223 __ sub(sp, sp, Operand(slots * kPointerSize)); |
| 192 } | 224 } |
| 193 } | 225 } |
| 194 | 226 |
| 195 if (info()->saves_caller_doubles()) { | 227 if (info()->saves_caller_doubles()) { |
| 196 Comment(";;; Save clobbered callee double registers"); | 228 SaveCallerDoubles(); |
| 197 int count = 0; | |
| 198 BitVector* doubles = chunk()->allocated_double_registers(); | |
| 199 BitVector::Iterator save_iterator(doubles); | |
| 200 while (!save_iterator.Done()) { | |
| 201 __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), | |
| 202 MemOperand(sp, count * kDoubleSize)); | |
| 203 save_iterator.Advance(); | |
| 204 count++; | |
| 205 } | |
| 206 } | 229 } |
| 207 | 230 |
| 208 // Possibly allocate a local context. | 231 // Possibly allocate a local context. |
| 209 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 232 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
| 210 if (heap_slots > 0) { | 233 if (heap_slots > 0) { |
| 211 Comment(";;; Allocate local context"); | 234 Comment(";;; Allocate local context"); |
| 212 // Argument to NewContext is the function, which is in r1. | 235 // Argument to NewContext is the function, which is in r1. |
| 213 __ push(r1); | 236 __ push(r1); |
| 214 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 237 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
| 215 FastNewContextStub stub(heap_slots); | 238 FastNewContextStub stub(heap_slots); |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 __ bind(&deopt_jump_table_[i].label); | 392 __ bind(&deopt_jump_table_[i].label); |
| 370 Address entry = deopt_jump_table_[i].address; | 393 Address entry = deopt_jump_table_[i].address; |
| 371 Deoptimizer::BailoutType type = deopt_jump_table_[i].bailout_type; | 394 Deoptimizer::BailoutType type = deopt_jump_table_[i].bailout_type; |
| 372 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); | 395 int id = Deoptimizer::GetDeoptimizationId(isolate(), entry, type); |
| 373 if (id == Deoptimizer::kNotDeoptimizationEntry) { | 396 if (id == Deoptimizer::kNotDeoptimizationEntry) { |
| 374 Comment(";;; jump table entry %d.", i); | 397 Comment(";;; jump table entry %d.", i); |
| 375 } else { | 398 } else { |
| 376 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); | 399 Comment(";;; jump table entry %d: deoptimization bailout %d.", i, id); |
| 377 } | 400 } |
| 378 if (deopt_jump_table_[i].needs_frame) { | 401 if (deopt_jump_table_[i].needs_frame) { |
| 402 ASSERT(!info()->saves_caller_doubles()); |
| 379 __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); | 403 __ mov(ip, Operand(ExternalReference::ForDeoptEntry(entry))); |
| 380 if (needs_frame.is_bound()) { | 404 if (needs_frame.is_bound()) { |
| 381 __ b(&needs_frame); | 405 __ b(&needs_frame); |
| 382 } else { | 406 } else { |
| 383 __ bind(&needs_frame); | 407 __ bind(&needs_frame); |
| 384 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 408 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
| 385 // This variant of deopt can only be used with stubs. Since we don't | 409 // This variant of deopt can only be used with stubs. Since we don't |
| 386 // have a function pointer to install in the stack frame that we're | 410 // have a function pointer to install in the stack frame that we're |
| 387 // building, install a special marker there instead. | 411 // building, install a special marker there instead. |
| 388 ASSERT(info()->IsStub()); | 412 ASSERT(info()->IsStub()); |
| 389 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | 413 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
| 390 __ push(scratch0()); | 414 __ push(scratch0()); |
| 391 __ add(fp, sp, Operand(2 * kPointerSize)); | 415 __ add(fp, sp, Operand(2 * kPointerSize)); |
| 392 __ mov(lr, Operand(pc), LeaveCC, al); | 416 __ mov(lr, Operand(pc), LeaveCC, al); |
| 393 __ mov(pc, ip); | 417 __ mov(pc, ip); |
| 394 } | 418 } |
| 395 } else { | 419 } else { |
| 420 if (info()->saves_caller_doubles()) { |
| 421 ASSERT(info()->IsStub()); |
| 422 RestoreCallerDoubles(); |
| 423 } |
| 396 __ mov(lr, Operand(pc), LeaveCC, al); | 424 __ mov(lr, Operand(pc), LeaveCC, al); |
| 397 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); | 425 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); |
| 398 } | 426 } |
| 399 masm()->CheckConstPool(false, false); | 427 masm()->CheckConstPool(false, false); |
| 400 } | 428 } |
| 401 | 429 |
| 402 // Force constant pool emission at the end of the deopt jump table to make | 430 // Force constant pool emission at the end of the deopt jump table to make |
| 403 // sure that no constant pools are emitted after. | 431 // sure that no constant pools are emitted after. |
| 404 masm()->CheckConstPool(true, false); | 432 masm()->CheckConstPool(true, false); |
| 405 | 433 |
| (...skipping 419 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 825 ASSERT(frame_is_built_); | 853 ASSERT(frame_is_built_); |
| 826 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 854 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 827 return; | 855 return; |
| 828 } | 856 } |
| 829 | 857 |
| 830 if (info()->ShouldTrapOnDeopt()) { | 858 if (info()->ShouldTrapOnDeopt()) { |
| 831 __ stop("trap_on_deopt", condition); | 859 __ stop("trap_on_deopt", condition); |
| 832 } | 860 } |
| 833 | 861 |
| 834 ASSERT(info()->IsStub() || frame_is_built_); | 862 ASSERT(info()->IsStub() || frame_is_built_); |
| 835 if (condition == al && frame_is_built_) { | 863 // Go through jump table if we need to handle condition, build frame, or |
| 864 // restore caller doubles. |
| 865 if (condition == al && frame_is_built_ && |
| 866 !info()->saves_caller_doubles()) { |
| 836 __ Call(entry, RelocInfo::RUNTIME_ENTRY); | 867 __ Call(entry, RelocInfo::RUNTIME_ENTRY); |
| 837 } else { | 868 } else { |
| 838 // We often have several deopts to the same entry, reuse the last | 869 // We often have several deopts to the same entry, reuse the last |
| 839 // jump entry if this is the case. | 870 // jump entry if this is the case. |
| 840 if (deopt_jump_table_.is_empty() || | 871 if (deopt_jump_table_.is_empty() || |
| 841 (deopt_jump_table_.last().address != entry) || | 872 (deopt_jump_table_.last().address != entry) || |
| 842 (deopt_jump_table_.last().bailout_type != bailout_type) || | 873 (deopt_jump_table_.last().bailout_type != bailout_type) || |
| 843 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { | 874 (deopt_jump_table_.last().needs_frame != !frame_is_built_)) { |
| 844 Deoptimizer::JumpTableEntry table_entry(entry, | 875 Deoptimizer::JumpTableEntry table_entry(entry, |
| 845 bailout_type, | 876 bailout_type, |
| (...skipping 2060 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2906 | 2937 |
| 2907 | 2938 |
| 2908 void LCodeGen::DoReturn(LReturn* instr) { | 2939 void LCodeGen::DoReturn(LReturn* instr) { |
| 2909 if (FLAG_trace && info()->IsOptimizing()) { | 2940 if (FLAG_trace && info()->IsOptimizing()) { |
| 2910 // Push the return value on the stack as the parameter. | 2941 // Push the return value on the stack as the parameter. |
| 2911 // Runtime::TraceExit returns its parameter in r0. | 2942 // Runtime::TraceExit returns its parameter in r0. |
| 2912 __ push(r0); | 2943 __ push(r0); |
| 2913 __ CallRuntime(Runtime::kTraceExit, 1); | 2944 __ CallRuntime(Runtime::kTraceExit, 1); |
| 2914 } | 2945 } |
| 2915 if (info()->saves_caller_doubles()) { | 2946 if (info()->saves_caller_doubles()) { |
| 2916 ASSERT(NeedsEagerFrame()); | 2947 RestoreCallerDoubles(); |
| 2917 BitVector* doubles = chunk()->allocated_double_registers(); | |
| 2918 BitVector::Iterator save_iterator(doubles); | |
| 2919 int count = 0; | |
| 2920 while (!save_iterator.Done()) { | |
| 2921 __ vldr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), | |
| 2922 MemOperand(sp, count * kDoubleSize)); | |
| 2923 save_iterator.Advance(); | |
| 2924 count++; | |
| 2925 } | |
| 2926 } | 2948 } |
| 2927 int no_frame_start = -1; | 2949 int no_frame_start = -1; |
| 2928 if (NeedsEagerFrame()) { | 2950 if (NeedsEagerFrame()) { |
| 2929 __ mov(sp, fp); | 2951 __ mov(sp, fp); |
| 2930 no_frame_start = masm_->pc_offset(); | 2952 no_frame_start = masm_->pc_offset(); |
| 2931 __ ldm(ia_w, sp, fp.bit() | lr.bit()); | 2953 __ ldm(ia_w, sp, fp.bit() | lr.bit()); |
| 2932 } | 2954 } |
| 2933 if (instr->has_constant_parameter_count()) { | 2955 if (instr->has_constant_parameter_count()) { |
| 2934 int parameter_count = ToInteger32(instr->constant_parameter_count()); | 2956 int parameter_count = ToInteger32(instr->constant_parameter_count()); |
| 2935 int32_t sp_delta = (parameter_count + 1) * kPointerSize; | 2957 int32_t sp_delta = (parameter_count + 1) * kPointerSize; |
| (...skipping 2851 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 5787 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5809 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
| 5788 __ ldr(result, FieldMemOperand(scratch, | 5810 __ ldr(result, FieldMemOperand(scratch, |
| 5789 FixedArray::kHeaderSize - kPointerSize)); | 5811 FixedArray::kHeaderSize - kPointerSize)); |
| 5790 __ bind(&done); | 5812 __ bind(&done); |
| 5791 } | 5813 } |
| 5792 | 5814 |
| 5793 | 5815 |
| 5794 #undef __ | 5816 #undef __ |
| 5795 | 5817 |
| 5796 } } // namespace v8::internal | 5818 } } // namespace v8::internal |
| OLD | NEW |