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 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
143 __ b(eq, &ok); | 143 __ b(eq, &ok); |
144 int receiver_offset = scope()->num_parameters() * kPointerSize; | 144 int receiver_offset = scope()->num_parameters() * kPointerSize; |
145 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); | 145 __ LoadRoot(r2, Heap::kUndefinedValueRootIndex); |
146 __ str(r2, MemOperand(sp, receiver_offset)); | 146 __ str(r2, MemOperand(sp, receiver_offset)); |
147 __ bind(&ok); | 147 __ bind(&ok); |
148 } | 148 } |
149 } | 149 } |
150 | 150 |
151 info()->set_prologue_offset(masm_->pc_offset()); | 151 info()->set_prologue_offset(masm_->pc_offset()); |
152 if (NeedsEagerFrame()) { | 152 if (NeedsEagerFrame()) { |
| 153 fp_sp_delta_ = 2 * kPointerSize; |
153 if (info()->IsStub()) { | 154 if (info()->IsStub()) { |
154 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 155 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
155 __ Push(Smi::FromInt(StackFrame::STUB)); | 156 __ Push(Smi::FromInt(StackFrame::STUB)); |
156 // Adjust FP to point to saved FP. | 157 // Adjust FP to point to saved FP. |
157 __ add(fp, sp, Operand(2 * kPointerSize)); | 158 __ add(fp, sp, Operand(fp_sp_delta_)); |
158 } else { | 159 } else { |
159 PredictableCodeSizeScope predictible_code_size_scope( | 160 PredictableCodeSizeScope predictible_code_size_scope( |
160 masm_, kNoCodeAgeSequenceLength * Assembler::kInstrSize); | 161 masm_, kNoCodeAgeSequenceLength * Assembler::kInstrSize); |
161 // The following three instructions must remain together and unmodified | 162 // The following three instructions must remain together and unmodified |
162 // for code aging to work properly. | 163 // for code aging to work properly. |
163 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); | 164 __ stm(db_w, sp, r1.bit() | cp.bit() | fp.bit() | lr.bit()); |
164 __ nop(ip.code()); | 165 __ nop(ip.code()); |
165 if (masm()->is_thumb_mode()) { | 166 if (masm()->is_thumb_mode()) { |
166 __ nop(ip.code()); | 167 __ nop(ip.code()); |
167 } | 168 } |
168 // Adjust FP to point to saved FP. | 169 // Adjust FP to point to saved FP. |
169 __ add(fp, sp, Operand(2 * kPointerSize)); | 170 __ add(fp, sp, Operand(fp_sp_delta_)); |
170 } | 171 } |
171 frame_is_built_ = true; | 172 frame_is_built_ = true; |
172 info_->AddNoFrameRange(0, masm_->pc_offset()); | 173 info_->AddNoFrameRange(0, masm_->pc_offset()); |
173 } | 174 } |
174 | 175 |
175 // Reserve space for the stack slots needed by the code. | 176 // Reserve space for the stack slots needed by the code. |
176 int slots = GetStackSlotCount(); | 177 int slots = GetStackSlotCount(); |
177 if (slots > 0) { | 178 if (slots > 0) { |
| 179 int slots_size = slots * kPointerSize; |
| 180 fp_sp_delta_ += slots_size; |
178 if (FLAG_debug_code) { | 181 if (FLAG_debug_code) { |
179 __ sub(sp, sp, Operand(slots * kPointerSize)); | 182 __ sub(sp, sp, Operand(slots_size)); |
180 __ push(r0); | 183 __ push(r0); |
181 __ push(r1); | 184 __ push(r1); |
182 __ add(r0, sp, Operand(slots * kPointerSize)); | 185 __ add(r0, sp, Operand(slots_size)); |
183 __ mov(r1, Operand(kSlotsZapValue)); | 186 __ mov(r1, Operand(kSlotsZapValue)); |
184 Label loop; | 187 Label loop; |
185 __ bind(&loop); | 188 __ bind(&loop); |
186 __ sub(r0, r0, Operand(kPointerSize)); | 189 __ sub(r0, r0, Operand(kPointerSize)); |
187 __ str(r1, MemOperand(r0, 2 * kPointerSize)); | 190 __ str(r1, MemOperand(r0, 2 * kPointerSize)); |
188 __ cmp(r0, sp); | 191 __ cmp(r0, sp); |
189 __ b(ne, &loop); | 192 __ b(ne, &loop); |
190 __ pop(r1); | 193 __ pop(r1); |
191 __ pop(r0); | 194 __ pop(r0); |
192 } else { | 195 } else { |
193 __ sub(sp, sp, Operand(slots * kPointerSize)); | 196 __ sub(sp, sp, Operand(slots_size)); |
194 } | 197 } |
195 } | 198 } |
196 | 199 |
197 if (info()->saves_caller_doubles()) { | 200 if (info()->saves_caller_doubles()) { |
198 Comment(";;; Save clobbered callee double registers"); | 201 Comment(";;; Save clobbered callee double registers"); |
199 int count = 0; | 202 int count = 0; |
200 BitVector* doubles = chunk()->allocated_double_registers(); | 203 BitVector* doubles = chunk()->allocated_double_registers(); |
201 BitVector::Iterator save_iterator(doubles); | 204 BitVector::Iterator save_iterator(doubles); |
202 while (!save_iterator.Done()) { | 205 while (!save_iterator.Done()) { |
203 __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), | 206 __ vstr(DwVfpRegister::FromAllocationIndex(save_iterator.Current()), |
204 MemOperand(sp, count * kDoubleSize)); | 207 MemOperand(sp, count * kDoubleSize)); |
205 save_iterator.Advance(); | 208 save_iterator.Advance(); |
206 count++; | 209 count++; |
207 } | 210 } |
208 } | 211 } |
209 | 212 |
210 // Possibly allocate a local context. | 213 // Possibly allocate a local context. |
211 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; | 214 int heap_slots = info()->num_heap_slots() - Context::MIN_CONTEXT_SLOTS; |
212 if (heap_slots > 0) { | 215 if (heap_slots > 0) { |
| 216 ASSERT(frame_is_built_); |
213 Comment(";;; Allocate local context"); | 217 Comment(";;; Allocate local context"); |
214 // Argument to NewContext is the function, which is in r1. | 218 // Argument to NewContext is the function, which is in r1. |
215 __ push(r1); | 219 __ push(r1); |
216 if (heap_slots <= FastNewContextStub::kMaximumSlots) { | 220 if (heap_slots <= FastNewContextStub::kMaximumSlots) { |
217 FastNewContextStub stub(heap_slots); | 221 FastNewContextStub stub(heap_slots); |
218 __ CallStub(&stub); | 222 __ CallStub(&stub); |
219 } else { | 223 } else { |
220 __ CallRuntime(Runtime::kNewFunctionContext, 1); | 224 __ CallRuntime(Runtime::kNewFunctionContext, 1); |
221 } | 225 } |
222 RecordSafepoint(Safepoint::kNoLazyDeopt); | 226 RecordSafepoint(Safepoint::kNoLazyDeopt); |
223 // Context is returned in both r0 and cp. It replaces the context | 227 // Context is returned in both r0 and cp. It replaces the context |
224 // passed to us. It's saved in the stack and kept live in cp. | 228 // passed to us. It's saved in the stack and kept live in cp. |
225 __ str(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 229 int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_; |
| 230 __ str(cp, MemOperand(sp, cp_offset)); |
226 // Copy any necessary parameters into the context. | 231 // Copy any necessary parameters into the context. |
227 int num_parameters = scope()->num_parameters(); | 232 int num_parameters = scope()->num_parameters(); |
228 for (int i = 0; i < num_parameters; i++) { | 233 for (int i = 0; i < num_parameters; i++) { |
229 Variable* var = scope()->parameter(i); | 234 Variable* var = scope()->parameter(i); |
230 if (var->IsContextSlot()) { | 235 if (var->IsContextSlot()) { |
231 int parameter_offset = StandardFrameConstants::kCallerSPOffset + | 236 int parameter_offset = StandardFrameConstants::kCallerSPOffset + |
232 (num_parameters - 1 - i) * kPointerSize; | 237 (num_parameters - 1 - i) * kPointerSize + fp_sp_delta_; |
233 // Load parameter from stack. | 238 // Load parameter from stack. |
234 __ ldr(r0, MemOperand(fp, parameter_offset)); | 239 __ ldr(r0, MemOperand(sp, parameter_offset)); |
235 // Store it in the context. | 240 // Store it in the context. |
236 MemOperand target = ContextOperand(cp, var->index()); | 241 MemOperand target = ContextOperand(cp, var->index()); |
237 __ str(r0, target); | 242 __ str(r0, target); |
238 // Update the write barrier. This clobbers r3 and r0. | 243 // Update the write barrier. This clobbers r3 and r0. |
239 __ RecordWriteContextSlot( | 244 __ RecordWriteContextSlot( |
240 cp, | 245 cp, |
241 target.offset(), | 246 target.offset(), |
242 r0, | 247 r0, |
243 r3, | 248 r3, |
244 GetLinkRegisterState(), | 249 GetLinkRegisterState(), |
(...skipping 14 matching lines...) Expand all Loading... |
259 bool LCodeGen::GenerateBody() { | 264 bool LCodeGen::GenerateBody() { |
260 ASSERT(is_generating()); | 265 ASSERT(is_generating()); |
261 bool emit_instructions = true; | 266 bool emit_instructions = true; |
262 for (current_instruction_ = 0; | 267 for (current_instruction_ = 0; |
263 !is_aborted() && current_instruction_ < instructions_->length(); | 268 !is_aborted() && current_instruction_ < instructions_->length(); |
264 current_instruction_++) { | 269 current_instruction_++) { |
265 LInstruction* instr = instructions_->at(current_instruction_); | 270 LInstruction* instr = instructions_->at(current_instruction_); |
266 | 271 |
267 // Don't emit code for basic blocks with a replacement. | 272 // Don't emit code for basic blocks with a replacement. |
268 if (instr->IsLabel()) { | 273 if (instr->IsLabel()) { |
269 emit_instructions = !LLabel::cast(instr)->HasReplacement(); | 274 LLabel* label = LLabel::cast(instr); |
| 275 emit_instructions = !label->HasReplacement(); |
| 276 if (emit_instructions) { |
| 277 HBasicBlock* block = label->block(); |
| 278 int argument_count = block->HasPredecessor() |
| 279 ? block->predecessors()->at(0)->argument_count() |
| 280 : 0; |
| 281 SetFpSpDelta(argument_count); |
| 282 } |
270 } | 283 } |
271 if (!emit_instructions) continue; | 284 if (!emit_instructions) continue; |
272 | 285 |
273 if (FLAG_code_comments && instr->HasInterestingComment(this)) { | 286 if (FLAG_code_comments && instr->HasInterestingComment(this)) { |
274 Comment(";;; <@%d,#%d> %s", | 287 Comment(";;; <@%d,#%d> %s", |
275 current_instruction_, | 288 current_instruction_, |
276 instr->hydrogen_value()->id(), | 289 instr->hydrogen_value()->id(), |
277 instr->Mnemonic()); | 290 instr->Mnemonic()); |
278 } | 291 } |
279 | 292 |
(...skipping 20 matching lines...) Expand all Loading... |
300 "-------------------- Deferred %s --------------------", | 313 "-------------------- Deferred %s --------------------", |
301 code->instruction_index(), | 314 code->instruction_index(), |
302 code->instr()->hydrogen_value()->id(), | 315 code->instr()->hydrogen_value()->id(), |
303 code->instr()->Mnemonic()); | 316 code->instr()->Mnemonic()); |
304 __ bind(code->entry()); | 317 __ bind(code->entry()); |
305 if (NeedsDeferredFrame()) { | 318 if (NeedsDeferredFrame()) { |
306 Comment(";;; Build frame"); | 319 Comment(";;; Build frame"); |
307 ASSERT(!frame_is_built_); | 320 ASSERT(!frame_is_built_); |
308 ASSERT(info()->IsStub()); | 321 ASSERT(info()->IsStub()); |
309 frame_is_built_ = true; | 322 frame_is_built_ = true; |
| 323 fp_sp_delta_ = 2 * kPointerSize; |
310 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 324 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
311 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | 325 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
312 __ push(scratch0()); | 326 __ push(scratch0()); |
313 __ add(fp, sp, Operand(2 * kPointerSize)); | 327 __ add(fp, sp, Operand(fp_sp_delta_)); |
314 Comment(";;; Deferred code"); | 328 Comment(";;; Deferred code"); |
315 } | 329 } |
316 code->Generate(); | 330 code->Generate(); |
317 if (NeedsDeferredFrame()) { | 331 if (NeedsDeferredFrame()) { |
318 Comment(";;; Destroy frame"); | 332 Comment(";;; Destroy frame"); |
319 ASSERT(frame_is_built_); | 333 ASSERT(frame_is_built_); |
320 __ pop(ip); | 334 __ pop(ip); |
321 __ ldm(ia_w, sp, cp.bit() | fp.bit() | lr.bit()); | 335 __ ldm(ia_w, sp, cp.bit() | fp.bit() | lr.bit()); |
322 frame_is_built_ = false; | 336 frame_is_built_ = false; |
| 337 fp_sp_delta_ = -1; |
323 } | 338 } |
324 __ jmp(code->exit()); | 339 __ jmp(code->exit()); |
325 } | 340 } |
326 } | 341 } |
327 | 342 |
328 // Force constant pool emission at the end of the deferred code to make | 343 // Force constant pool emission at the end of the deferred code to make |
329 // sure that no constant pools are emitted after. | 344 // sure that no constant pools are emitted after. |
330 masm()->CheckConstPool(true, false); | 345 masm()->CheckConstPool(true, false); |
331 | 346 |
332 return !is_aborted(); | 347 return !is_aborted(); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 __ b(&needs_frame); | 383 __ b(&needs_frame); |
369 } else { | 384 } else { |
370 __ bind(&needs_frame); | 385 __ bind(&needs_frame); |
371 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); | 386 __ stm(db_w, sp, cp.bit() | fp.bit() | lr.bit()); |
372 // This variant of deopt can only be used with stubs. Since we don't | 387 // This variant of deopt can only be used with stubs. Since we don't |
373 // have a function pointer to install in the stack frame that we're | 388 // have a function pointer to install in the stack frame that we're |
374 // building, install a special marker there instead. | 389 // building, install a special marker there instead. |
375 ASSERT(info()->IsStub()); | 390 ASSERT(info()->IsStub()); |
376 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); | 391 __ mov(scratch0(), Operand(Smi::FromInt(StackFrame::STUB))); |
377 __ push(scratch0()); | 392 __ push(scratch0()); |
378 __ add(fp, sp, Operand(2 * kPointerSize)); | 393 fp_sp_delta_ = 2 * kPointerSize; |
| 394 __ add(fp, sp, Operand(fp_sp_delta_)); |
379 __ mov(lr, Operand(pc), LeaveCC, al); | 395 __ mov(lr, Operand(pc), LeaveCC, al); |
380 __ mov(pc, ip); | 396 __ mov(pc, ip); |
381 } | 397 } |
382 } else { | 398 } else { |
383 __ mov(lr, Operand(pc), LeaveCC, al); | 399 __ mov(lr, Operand(pc), LeaveCC, al); |
384 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); | 400 __ mov(pc, Operand(ExternalReference::ForDeoptEntry(entry))); |
385 } | 401 } |
386 masm()->CheckConstPool(false, false); | 402 masm()->CheckConstPool(false, false); |
387 } | 403 } |
388 | 404 |
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 // Stack slots not implemented, use ToMemOperand instead. | 572 // Stack slots not implemented, use ToMemOperand instead. |
557 UNREACHABLE(); | 573 UNREACHABLE(); |
558 return Operand::Zero(); | 574 return Operand::Zero(); |
559 } | 575 } |
560 | 576 |
561 | 577 |
562 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { | 578 MemOperand LCodeGen::ToMemOperand(LOperand* op) const { |
563 ASSERT(!op->IsRegister()); | 579 ASSERT(!op->IsRegister()); |
564 ASSERT(!op->IsDoubleRegister()); | 580 ASSERT(!op->IsDoubleRegister()); |
565 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); | 581 ASSERT(op->IsStackSlot() || op->IsDoubleStackSlot()); |
566 return MemOperand(fp, StackSlotOffset(op->index())); | 582 return MemOperand(sp, StackSlotOffset(op->index(), fp_sp_delta_)); |
567 } | 583 } |
568 | 584 |
569 | 585 |
570 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const { | 586 MemOperand LCodeGen::ToHighMemOperand(LOperand* op) const { |
571 ASSERT(op->IsDoubleStackSlot()); | 587 ASSERT(op->IsDoubleStackSlot()); |
572 return MemOperand(fp, StackSlotOffset(op->index()) + kPointerSize); | 588 int offset = StackSlotOffset(op->index(), fp_sp_delta_) + kPointerSize; |
| 589 return MemOperand(sp, offset); |
573 } | 590 } |
574 | 591 |
575 | 592 |
576 void LCodeGen::WriteTranslation(LEnvironment* environment, | 593 void LCodeGen::WriteTranslation(LEnvironment* environment, |
577 Translation* translation) { | 594 Translation* translation) { |
578 if (environment == NULL) return; | 595 if (environment == NULL) return; |
579 | 596 |
580 // The translation includes one command per value in the environment. | 597 // The translation includes one command per value in the environment. |
581 int translation_size = environment->translation_size(); | 598 int translation_size = environment->translation_size(); |
582 // The output frame height does not include the parameters. | 599 // The output frame height does not include the parameters. |
(...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
694 } else if (op->IsConstantOperand()) { | 711 } else if (op->IsConstantOperand()) { |
695 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); | 712 HConstant* constant = chunk()->LookupConstant(LConstantOperand::cast(op)); |
696 int src_index = DefineDeoptimizationLiteral(constant->handle()); | 713 int src_index = DefineDeoptimizationLiteral(constant->handle()); |
697 translation->StoreLiteral(src_index); | 714 translation->StoreLiteral(src_index); |
698 } else { | 715 } else { |
699 UNREACHABLE(); | 716 UNREACHABLE(); |
700 } | 717 } |
701 } | 718 } |
702 | 719 |
703 | 720 |
| 721 void LCodeGen::SetFpSpDelta(int argument_count) { |
| 722 int slots_size = GetStackSlotCount() * kPointerSize; |
| 723 int args_size = argument_count * kPointerSize; |
| 724 int fixed_size = 2 * kPointerSize; |
| 725 fp_sp_delta_ = slots_size + args_size + fixed_size; |
| 726 } |
| 727 |
| 728 |
| 729 void LCodeGen::Push(Register src1) { |
| 730 fp_sp_delta_ += kPointerSize; |
| 731 __ push(src1); |
| 732 } |
| 733 |
| 734 |
| 735 void LCodeGen::Push(Register src1, Register src2) { |
| 736 fp_sp_delta_ += 2 * kPointerSize; |
| 737 __ Push(src1, src2); |
| 738 } |
| 739 |
| 740 |
| 741 void LCodeGen::Push(Register src1, Register src2, Register src3) { |
| 742 fp_sp_delta_ += 3 * kPointerSize; |
| 743 __ Push(src1, src2, src3); |
| 744 } |
| 745 |
| 746 |
| 747 void LCodeGen::Push(Register src1, |
| 748 Register src2, |
| 749 Register src3, |
| 750 Register src4) { |
| 751 fp_sp_delta_ += 4 * kPointerSize; |
| 752 __ Push(src1, src2, src3, src4); |
| 753 } |
| 754 |
| 755 |
| 756 #ifdef DEBUG |
| 757 void LCodeGen::CheckFpSpDelta(LInstruction* instr) { |
| 758 if (fp_sp_delta_ == -1 || !instr->HasEnvironment()) |
| 759 return; |
| 760 int slots_size = GetStackSlotCount() * kPointerSize; |
| 761 int args_size = instr->environment()->arguments_stack_height() * kPointerSize; |
| 762 int fixed_size = 2 * kPointerSize; |
| 763 int expected_delta = slots_size + args_size + fixed_size; |
| 764 ASSERT_EQ(expected_delta, fp_sp_delta_); |
| 765 } |
| 766 #endif // DEBUG |
| 767 |
| 768 |
704 void LCodeGen::CallCode(Handle<Code> code, | 769 void LCodeGen::CallCode(Handle<Code> code, |
705 RelocInfo::Mode mode, | 770 RelocInfo::Mode mode, |
| 771 int num_arguments, |
706 LInstruction* instr, | 772 LInstruction* instr, |
707 TargetAddressStorageMode storage_mode) { | 773 TargetAddressStorageMode storage_mode) { |
708 CallCodeGeneric(code, mode, instr, RECORD_SIMPLE_SAFEPOINT, storage_mode); | 774 CallCodeGeneric(code, mode, num_arguments, instr, RECORD_SIMPLE_SAFEPOINT, |
| 775 storage_mode); |
709 } | 776 } |
710 | 777 |
711 | 778 |
712 void LCodeGen::CallCodeGeneric(Handle<Code> code, | 779 void LCodeGen::CallCodeGeneric(Handle<Code> code, |
713 RelocInfo::Mode mode, | 780 RelocInfo::Mode mode, |
| 781 int num_arguments, |
714 LInstruction* instr, | 782 LInstruction* instr, |
715 SafepointMode safepoint_mode, | 783 SafepointMode safepoint_mode, |
716 TargetAddressStorageMode storage_mode) { | 784 TargetAddressStorageMode storage_mode) { |
717 EnsureSpaceForLazyDeopt(); | 785 EnsureSpaceForLazyDeopt(); |
718 ASSERT(instr != NULL); | 786 ASSERT(instr != NULL); |
719 // Block literal pool emission to ensure nop indicating no inlined smi code | 787 // Block literal pool emission to ensure nop indicating no inlined smi code |
720 // is in the correct position. | 788 // is in the correct position. |
721 Assembler::BlockConstPoolScope block_const_pool(masm()); | 789 Assembler::BlockConstPoolScope block_const_pool(masm()); |
722 LPointerMap* pointers = instr->pointer_map(); | 790 LPointerMap* pointers = instr->pointer_map(); |
723 RecordPosition(pointers->position()); | 791 RecordPosition(pointers->position()); |
724 __ Call(code, mode, TypeFeedbackId::None(), al, storage_mode); | 792 __ Call(code, mode, TypeFeedbackId::None(), al, storage_mode); |
| 793 fp_sp_delta_ -= num_arguments * kPointerSize; |
725 RecordSafepointWithLazyDeopt(instr, safepoint_mode); | 794 RecordSafepointWithLazyDeopt(instr, safepoint_mode); |
726 | 795 |
727 // Signal that we don't inline smi code before these stubs in the | 796 // Signal that we don't inline smi code before these stubs in the |
728 // optimizing code generator. | 797 // optimizing code generator. |
729 if (code->kind() == Code::BINARY_OP_IC || | 798 if (code->kind() == Code::BINARY_OP_IC || |
730 code->kind() == Code::COMPARE_IC) { | 799 code->kind() == Code::COMPARE_IC) { |
731 __ nop(); | 800 __ nop(); |
732 } | 801 } |
733 } | 802 } |
734 | 803 |
735 | 804 |
736 void LCodeGen::CallRuntime(const Runtime::Function* function, | 805 void LCodeGen::CallRuntime(const Runtime::Function* function, |
737 int num_arguments, | 806 int num_arguments, |
738 LInstruction* instr) { | 807 LInstruction* instr) { |
739 ASSERT(instr != NULL); | 808 ASSERT(instr != NULL); |
740 LPointerMap* pointers = instr->pointer_map(); | 809 LPointerMap* pointers = instr->pointer_map(); |
741 ASSERT(pointers != NULL); | 810 ASSERT(pointers != NULL); |
742 RecordPosition(pointers->position()); | 811 RecordPosition(pointers->position()); |
743 | 812 |
744 __ CallRuntime(function, num_arguments); | 813 __ CallRuntime(function, num_arguments); |
| 814 fp_sp_delta_ -= num_arguments * kPointerSize; |
745 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 815 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
746 } | 816 } |
747 | 817 |
748 | 818 |
749 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, | 819 void LCodeGen::CallRuntimeFromDeferred(Runtime::FunctionId id, |
750 int argc, | 820 int argc, |
751 LInstruction* instr) { | 821 LInstruction* instr) { |
752 __ CallRuntimeSaveDoubles(id); | 822 __ CallRuntimeSaveDoubles(id); |
| 823 fp_sp_delta_ -= argc * kPointerSize; |
753 RecordSafepointWithRegisters( | 824 RecordSafepointWithRegisters( |
754 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); | 825 instr->pointer_map(), argc, Safepoint::kNoLazyDeopt); |
755 } | 826 } |
756 | 827 |
757 | 828 |
758 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, | 829 void LCodeGen::RegisterEnvironmentForDeoptimization(LEnvironment* environment, |
759 Safepoint::DeoptMode mode) { | 830 Safepoint::DeoptMode mode) { |
760 if (!environment->HasBeenRegistered()) { | 831 if (!environment->HasBeenRegistered()) { |
761 // Physical stack frame layout: | 832 // Physical stack frame layout: |
762 // -x ............. -4 0 ..................................... y | 833 // -x ............. -4 0 ..................................... y |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1062 void LCodeGen::DoParameter(LParameter* instr) { | 1133 void LCodeGen::DoParameter(LParameter* instr) { |
1063 // Nothing to do. | 1134 // Nothing to do. |
1064 } | 1135 } |
1065 | 1136 |
1066 | 1137 |
1067 void LCodeGen::DoCallStub(LCallStub* instr) { | 1138 void LCodeGen::DoCallStub(LCallStub* instr) { |
1068 ASSERT(ToRegister(instr->result()).is(r0)); | 1139 ASSERT(ToRegister(instr->result()).is(r0)); |
1069 switch (instr->hydrogen()->major_key()) { | 1140 switch (instr->hydrogen()->major_key()) { |
1070 case CodeStub::RegExpConstructResult: { | 1141 case CodeStub::RegExpConstructResult: { |
1071 RegExpConstructResultStub stub; | 1142 RegExpConstructResultStub stub; |
1072 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1143 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 3, instr); |
1073 break; | 1144 break; |
1074 } | 1145 } |
1075 case CodeStub::RegExpExec: { | 1146 case CodeStub::RegExpExec: { |
1076 RegExpExecStub stub; | 1147 RegExpExecStub stub; |
1077 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1148 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 4, instr); |
1078 break; | 1149 break; |
1079 } | 1150 } |
1080 case CodeStub::SubString: { | 1151 case CodeStub::SubString: { |
1081 SubStringStub stub; | 1152 SubStringStub stub; |
1082 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1153 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 3, instr); |
1083 break; | 1154 break; |
1084 } | 1155 } |
1085 case CodeStub::NumberToString: { | 1156 case CodeStub::NumberToString: { |
1086 NumberToStringStub stub; | 1157 NumberToStringStub stub; |
1087 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1158 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 1, instr); |
1088 break; | 1159 break; |
1089 } | 1160 } |
1090 case CodeStub::StringCompare: { | 1161 case CodeStub::StringCompare: { |
1091 StringCompareStub stub; | 1162 StringCompareStub stub; |
1092 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1163 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2, instr); |
1093 break; | 1164 break; |
1094 } | 1165 } |
1095 case CodeStub::TranscendentalCache: { | 1166 case CodeStub::TranscendentalCache: { |
1096 __ ldr(r0, MemOperand(sp, 0)); | 1167 __ ldr(r0, MemOperand(sp, 0)); |
1097 TranscendentalCacheStub stub(instr->transcendental_type(), | 1168 TranscendentalCacheStub stub(instr->transcendental_type(), |
1098 TranscendentalCacheStub::TAGGED); | 1169 TranscendentalCacheStub::TAGGED); |
1099 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 1170 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 1, instr); |
1100 break; | 1171 break; |
1101 } | 1172 } |
1102 default: | 1173 default: |
1103 UNREACHABLE(); | 1174 UNREACHABLE(); |
1104 } | 1175 } |
1105 } | 1176 } |
1106 | 1177 |
1107 | 1178 |
1108 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { | 1179 void LCodeGen::DoUnknownOSRValue(LUnknownOSRValue* instr) { |
1109 // Record the address of the first unknown OSR value as the place to enter. | 1180 // Record the address of the first unknown OSR value as the place to enter. |
(...skipping 885 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1995 // MemOperand with ip as the base register is not allowed for strh, so | 2066 // MemOperand with ip as the base register is not allowed for strh, so |
1996 // we do the address calculation explicitly. | 2067 // we do the address calculation explicitly. |
1997 __ add(ip, ip, Operand(index, LSL, 1)); | 2068 __ add(ip, ip, Operand(index, LSL, 1)); |
1998 __ strh(value, MemOperand(ip)); | 2069 __ strh(value, MemOperand(ip)); |
1999 } | 2070 } |
2000 } | 2071 } |
2001 | 2072 |
2002 | 2073 |
2003 void LCodeGen::DoThrow(LThrow* instr) { | 2074 void LCodeGen::DoThrow(LThrow* instr) { |
2004 Register input_reg = EmitLoadRegister(instr->value(), ip); | 2075 Register input_reg = EmitLoadRegister(instr->value(), ip); |
2005 __ push(input_reg); | 2076 Push(input_reg); |
2006 CallRuntime(Runtime::kThrow, 1, instr); | 2077 CallRuntime(Runtime::kThrow, 1, instr); |
2007 | 2078 |
2008 if (FLAG_debug_code) { | 2079 if (FLAG_debug_code) { |
2009 __ stop("Unreachable code."); | 2080 __ stop("Unreachable code."); |
2010 } | 2081 } |
2011 } | 2082 } |
2012 | 2083 |
2013 | 2084 |
2014 void LCodeGen::DoAddI(LAddI* instr) { | 2085 void LCodeGen::DoAddI(LAddI* instr) { |
2015 LOperand* left = instr->left(); | 2086 LOperand* left = instr->left(); |
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2112 break; | 2183 break; |
2113 case Token::MUL: | 2184 case Token::MUL: |
2114 __ vmul(result, left, right); | 2185 __ vmul(result, left, right); |
2115 break; | 2186 break; |
2116 case Token::DIV: | 2187 case Token::DIV: |
2117 __ vdiv(result, left, right); | 2188 __ vdiv(result, left, right); |
2118 break; | 2189 break; |
2119 case Token::MOD: { | 2190 case Token::MOD: { |
2120 // Save r0-r3 on the stack. | 2191 // Save r0-r3 on the stack. |
2121 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); | 2192 __ stm(db_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); |
2122 | 2193 fp_sp_delta_ += 4 * kPointerSize; |
2123 __ PrepareCallCFunction(0, 2, scratch0()); | 2194 __ PrepareCallCFunction(0, 2, scratch0()); |
2124 __ SetCallCDoubleArguments(left, right); | 2195 __ SetCallCDoubleArguments(left, right); |
2125 __ CallCFunction( | 2196 __ CallCFunction( |
2126 ExternalReference::double_fp_operation(Token::MOD, isolate()), | 2197 ExternalReference::double_fp_operation(Token::MOD, isolate()), |
2127 0, 2); | 2198 0, 2); |
2128 // Move the result in the double result register. | 2199 // Move the result in the double result register. |
2129 __ GetCFunctionDoubleResult(result); | 2200 __ GetCFunctionDoubleResult(result); |
2130 | 2201 |
2131 // Restore r0-r3. | 2202 // Restore r0-r3. |
2132 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); | 2203 __ ldm(ia_w, sp, r0.bit() | r1.bit() | r2.bit() | r3.bit()); |
| 2204 fp_sp_delta_ -= 4 * kPointerSize; |
2133 break; | 2205 break; |
2134 } | 2206 } |
2135 default: | 2207 default: |
2136 UNREACHABLE(); | 2208 UNREACHABLE(); |
2137 break; | 2209 break; |
2138 } | 2210 } |
2139 } | 2211 } |
2140 | 2212 |
2141 | 2213 |
2142 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { | 2214 void LCodeGen::DoArithmeticT(LArithmeticT* instr) { |
2143 ASSERT(ToRegister(instr->left()).is(r1)); | 2215 ASSERT(ToRegister(instr->left()).is(r1)); |
2144 ASSERT(ToRegister(instr->right()).is(r0)); | 2216 ASSERT(ToRegister(instr->right()).is(r0)); |
2145 ASSERT(ToRegister(instr->result()).is(r0)); | 2217 ASSERT(ToRegister(instr->result()).is(r0)); |
2146 | 2218 |
2147 BinaryOpStub stub(instr->op(), NO_OVERWRITE); | 2219 BinaryOpStub stub(instr->op(), NO_OVERWRITE); |
2148 // Block literal pool emission to ensure nop indicating no inlined smi code | 2220 // Block literal pool emission to ensure nop indicating no inlined smi code |
2149 // is in the correct position. | 2221 // is in the correct position. |
2150 Assembler::BlockConstPoolScope block_const_pool(masm()); | 2222 Assembler::BlockConstPoolScope block_const_pool(masm()); |
2151 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2223 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr); |
2152 __ nop(); // Signals no inlined code. | 2224 __ nop(); // Signals no inlined code. |
2153 } | 2225 } |
2154 | 2226 |
2155 | 2227 |
2156 int LCodeGen::GetNextEmittedBlock() const { | 2228 int LCodeGen::GetNextEmittedBlock() const { |
2157 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { | 2229 for (int i = current_block_ + 1; i < graph()->blocks()->length(); ++i) { |
2158 if (!chunk_->GetLabel(i)->HasReplacement()) return i; | 2230 if (!chunk_->GetLabel(i)->HasReplacement()) return i; |
2159 } | 2231 } |
2160 return -1; | 2232 return -1; |
2161 } | 2233 } |
(...skipping 404 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2566 UNREACHABLE(); | 2638 UNREACHABLE(); |
2567 return kNoCondition; | 2639 return kNoCondition; |
2568 } | 2640 } |
2569 } | 2641 } |
2570 | 2642 |
2571 | 2643 |
2572 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { | 2644 void LCodeGen::DoStringCompareAndBranch(LStringCompareAndBranch* instr) { |
2573 Token::Value op = instr->op(); | 2645 Token::Value op = instr->op(); |
2574 | 2646 |
2575 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2647 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2576 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2648 CallCode(ic, RelocInfo::CODE_TARGET, 0, instr); |
2577 // This instruction also signals no smi code inlined. | 2649 // This instruction also signals no smi code inlined. |
2578 __ cmp(r0, Operand::Zero()); | 2650 __ cmp(r0, Operand::Zero()); |
2579 | 2651 |
2580 Condition condition = ComputeCompareCondition(op); | 2652 Condition condition = ComputeCompareCondition(op); |
2581 | 2653 |
2582 EmitBranch(instr, condition); | 2654 EmitBranch(instr, condition); |
2583 } | 2655 } |
2584 | 2656 |
2585 | 2657 |
2586 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { | 2658 static InstanceType TestType(HHasInstanceTypeAndBranch* instr) { |
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2727 __ cmp(temp, Operand(instr->map())); | 2799 __ cmp(temp, Operand(instr->map())); |
2728 EmitBranch(instr, eq); | 2800 EmitBranch(instr, eq); |
2729 } | 2801 } |
2730 | 2802 |
2731 | 2803 |
2732 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { | 2804 void LCodeGen::DoInstanceOf(LInstanceOf* instr) { |
2733 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. | 2805 ASSERT(ToRegister(instr->left()).is(r0)); // Object is in r0. |
2734 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. | 2806 ASSERT(ToRegister(instr->right()).is(r1)); // Function is in r1. |
2735 | 2807 |
2736 InstanceofStub stub(InstanceofStub::kArgsInRegisters); | 2808 InstanceofStub stub(InstanceofStub::kArgsInRegisters); |
2737 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 2809 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr); |
2738 | 2810 |
2739 __ cmp(r0, Operand::Zero()); | 2811 __ cmp(r0, Operand::Zero()); |
2740 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); | 2812 __ mov(r0, Operand(factory()->false_value()), LeaveCC, ne); |
2741 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); | 2813 __ mov(r0, Operand(factory()->true_value()), LeaveCC, eq); |
2742 } | 2814 } |
2743 | 2815 |
2744 | 2816 |
2745 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { | 2817 void LCodeGen::DoInstanceOfKnownGlobal(LInstanceOfKnownGlobal* instr) { |
2746 class DeferredInstanceOfKnownGlobal: public LDeferredCode { | 2818 class DeferredInstanceOfKnownGlobal: public LDeferredCode { |
2747 public: | 2819 public: |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2869 if (masm_->SizeOfCodeGeneratedSince(&before_push_delta) != 8) { | 2941 if (masm_->SizeOfCodeGeneratedSince(&before_push_delta) != 8) { |
2870 ASSERT_EQ(1, masm_->InstructionsGeneratedSince(&before_push_delta)); | 2942 ASSERT_EQ(1, masm_->InstructionsGeneratedSince(&before_push_delta)); |
2871 __ nop(); | 2943 __ nop(); |
2872 if (masm_->is_thumb_mode()) { | 2944 if (masm_->is_thumb_mode()) { |
2873 __ nop(); | 2945 __ nop(); |
2874 } | 2946 } |
2875 } | 2947 } |
2876 __ StoreToSafepointRegisterSlot(temp, temp); | 2948 __ StoreToSafepointRegisterSlot(temp, temp); |
2877 CallCodeGeneric(stub.GetCode(isolate()), | 2949 CallCodeGeneric(stub.GetCode(isolate()), |
2878 RelocInfo::CODE_TARGET, | 2950 RelocInfo::CODE_TARGET, |
| 2951 0, |
2879 instr, | 2952 instr, |
2880 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); | 2953 RECORD_SAFEPOINT_WITH_REGISTERS_AND_NO_ARGUMENTS); |
2881 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); | 2954 LEnvironment* env = instr->GetDeferredLazyDeoptimizationEnvironment(); |
2882 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 2955 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
2883 // Put the result value into the result register slot and | 2956 // Put the result value into the result register slot and |
2884 // restore all registers. | 2957 // restore all registers. |
2885 __ StoreToSafepointRegisterSlot(result, result); | 2958 __ StoreToSafepointRegisterSlot(result, result); |
2886 } | 2959 } |
2887 | 2960 |
2888 | 2961 |
2889 void LCodeGen::DoInstanceSize(LInstanceSize* instr) { | 2962 void LCodeGen::DoInstanceSize(LInstanceSize* instr) { |
2890 Register object = ToRegister(instr->object()); | 2963 Register object = ToRegister(instr->object()); |
2891 Register result = ToRegister(instr->result()); | 2964 Register result = ToRegister(instr->result()); |
2892 __ ldr(result, FieldMemOperand(object, HeapObject::kMapOffset)); | 2965 __ ldr(result, FieldMemOperand(object, HeapObject::kMapOffset)); |
2893 __ ldrb(result, FieldMemOperand(result, Map::kInstanceSizeOffset)); | 2966 __ ldrb(result, FieldMemOperand(result, Map::kInstanceSizeOffset)); |
2894 } | 2967 } |
2895 | 2968 |
2896 | 2969 |
2897 void LCodeGen::DoCmpT(LCmpT* instr) { | 2970 void LCodeGen::DoCmpT(LCmpT* instr) { |
2898 Token::Value op = instr->op(); | 2971 Token::Value op = instr->op(); |
2899 | 2972 |
2900 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); | 2973 Handle<Code> ic = CompareIC::GetUninitialized(isolate(), op); |
2901 CallCode(ic, RelocInfo::CODE_TARGET, instr); | 2974 CallCode(ic, RelocInfo::CODE_TARGET, 0, instr); |
2902 // This instruction also signals no smi code inlined. | 2975 // This instruction also signals no smi code inlined. |
2903 __ cmp(r0, Operand::Zero()); | 2976 __ cmp(r0, Operand::Zero()); |
2904 | 2977 |
2905 Condition condition = ComputeCompareCondition(op); | 2978 Condition condition = ComputeCompareCondition(op); |
2906 __ LoadRoot(ToRegister(instr->result()), | 2979 __ LoadRoot(ToRegister(instr->result()), |
2907 Heap::kTrueValueRootIndex, | 2980 Heap::kTrueValueRootIndex, |
2908 condition); | 2981 condition); |
2909 __ LoadRoot(ToRegister(instr->result()), | 2982 __ LoadRoot(ToRegister(instr->result()), |
2910 Heap::kFalseValueRootIndex, | 2983 Heap::kFalseValueRootIndex, |
2911 NegateCondition(condition)); | 2984 NegateCondition(condition)); |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2971 | 3044 |
2972 | 3045 |
2973 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { | 3046 void LCodeGen::DoLoadGlobalGeneric(LLoadGlobalGeneric* instr) { |
2974 ASSERT(ToRegister(instr->global_object()).is(r0)); | 3047 ASSERT(ToRegister(instr->global_object()).is(r0)); |
2975 ASSERT(ToRegister(instr->result()).is(r0)); | 3048 ASSERT(ToRegister(instr->result()).is(r0)); |
2976 | 3049 |
2977 __ mov(r2, Operand(instr->name())); | 3050 __ mov(r2, Operand(instr->name())); |
2978 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET | 3051 RelocInfo::Mode mode = instr->for_typeof() ? RelocInfo::CODE_TARGET |
2979 : RelocInfo::CODE_TARGET_CONTEXT; | 3052 : RelocInfo::CODE_TARGET_CONTEXT; |
2980 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3053 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
2981 CallCode(ic, mode, instr); | 3054 CallCode(ic, mode, 0, instr); |
2982 } | 3055 } |
2983 | 3056 |
2984 | 3057 |
2985 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { | 3058 void LCodeGen::DoStoreGlobalCell(LStoreGlobalCell* instr) { |
2986 Register value = ToRegister(instr->value()); | 3059 Register value = ToRegister(instr->value()); |
2987 Register cell = scratch0(); | 3060 Register cell = scratch0(); |
2988 | 3061 |
2989 // Load the cell. | 3062 // Load the cell. |
2990 __ mov(cell, Operand(instr->hydrogen()->cell())); | 3063 __ mov(cell, Operand(instr->hydrogen()->cell())); |
2991 | 3064 |
(...skipping 16 matching lines...) Expand all Loading... |
3008 | 3081 |
3009 | 3082 |
3010 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { | 3083 void LCodeGen::DoStoreGlobalGeneric(LStoreGlobalGeneric* instr) { |
3011 ASSERT(ToRegister(instr->global_object()).is(r1)); | 3084 ASSERT(ToRegister(instr->global_object()).is(r1)); |
3012 ASSERT(ToRegister(instr->value()).is(r0)); | 3085 ASSERT(ToRegister(instr->value()).is(r0)); |
3013 | 3086 |
3014 __ mov(r2, Operand(instr->name())); | 3087 __ mov(r2, Operand(instr->name())); |
3015 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 3088 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
3016 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 3089 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
3017 : isolate()->builtins()->StoreIC_Initialize(); | 3090 : isolate()->builtins()->StoreIC_Initialize(); |
3018 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, instr); | 3091 CallCode(ic, RelocInfo::CODE_TARGET_CONTEXT, 0, instr); |
3019 } | 3092 } |
3020 | 3093 |
3021 | 3094 |
3022 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { | 3095 void LCodeGen::DoLoadContextSlot(LLoadContextSlot* instr) { |
3023 Register context = ToRegister(instr->context()); | 3096 Register context = ToRegister(instr->context()); |
3024 Register result = ToRegister(instr->result()); | 3097 Register result = ToRegister(instr->result()); |
3025 __ ldr(result, ContextOperand(context, instr->slot_index())); | 3098 __ ldr(result, ContextOperand(context, instr->slot_index())); |
3026 if (instr->hydrogen()->RequiresHoleCheck()) { | 3099 if (instr->hydrogen()->RequiresHoleCheck()) { |
3027 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); | 3100 __ LoadRoot(ip, Heap::kTheHoleValueRootIndex); |
3028 __ cmp(result, ip); | 3101 __ cmp(result, ip); |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3100 } | 3173 } |
3101 | 3174 |
3102 | 3175 |
3103 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { | 3176 void LCodeGen::DoLoadNamedGeneric(LLoadNamedGeneric* instr) { |
3104 ASSERT(ToRegister(instr->object()).is(r0)); | 3177 ASSERT(ToRegister(instr->object()).is(r0)); |
3105 ASSERT(ToRegister(instr->result()).is(r0)); | 3178 ASSERT(ToRegister(instr->result()).is(r0)); |
3106 | 3179 |
3107 // Name is always in r2. | 3180 // Name is always in r2. |
3108 __ mov(r2, Operand(instr->name())); | 3181 __ mov(r2, Operand(instr->name())); |
3109 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); | 3182 Handle<Code> ic = isolate()->builtins()->LoadIC_Initialize(); |
3110 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 3183 CallCode(ic, RelocInfo::CODE_TARGET, 0, instr, NEVER_INLINE_TARGET_ADDRESS); |
3111 } | 3184 } |
3112 | 3185 |
3113 | 3186 |
3114 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { | 3187 void LCodeGen::DoLoadFunctionPrototype(LLoadFunctionPrototype* instr) { |
3115 Register scratch = scratch0(); | 3188 Register scratch = scratch0(); |
3116 Register function = ToRegister(instr->function()); | 3189 Register function = ToRegister(instr->function()); |
3117 Register result = ToRegister(instr->result()); | 3190 Register result = ToRegister(instr->result()); |
3118 | 3191 |
3119 // Check that the function really is a function. Load map into the | 3192 // Check that the function really is a function. Load map into the |
3120 // result register. | 3193 // result register. |
(...skipping 264 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3385 return MemOperand(base, scratch0(), LSR, 1); | 3458 return MemOperand(base, scratch0(), LSR, 1); |
3386 } | 3459 } |
3387 } | 3460 } |
3388 | 3461 |
3389 | 3462 |
3390 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { | 3463 void LCodeGen::DoLoadKeyedGeneric(LLoadKeyedGeneric* instr) { |
3391 ASSERT(ToRegister(instr->object()).is(r1)); | 3464 ASSERT(ToRegister(instr->object()).is(r1)); |
3392 ASSERT(ToRegister(instr->key()).is(r0)); | 3465 ASSERT(ToRegister(instr->key()).is(r0)); |
3393 | 3466 |
3394 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); | 3467 Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Initialize(); |
3395 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 3468 CallCode(ic, RelocInfo::CODE_TARGET, 0, instr, NEVER_INLINE_TARGET_ADDRESS); |
3396 } | 3469 } |
3397 | 3470 |
3398 | 3471 |
3399 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { | 3472 void LCodeGen::DoArgumentsElements(LArgumentsElements* instr) { |
3400 Register scratch = scratch0(); | 3473 Register scratch = scratch0(); |
3401 Register result = ToRegister(instr->result()); | 3474 Register result = ToRegister(instr->result()); |
3402 | 3475 |
3403 if (instr->hydrogen()->from_inlined()) { | 3476 if (instr->hydrogen()->from_inlined()) { |
3404 __ sub(result, sp, Operand(2 * kPointerSize)); | 3477 __ sub(result, sp, Operand(2 * kPointerSize)); |
3405 } else { | 3478 } else { |
3406 // Check if the calling frame is an arguments adaptor frame. | 3479 // Check if the calling frame is an arguments adaptor frame. |
3407 Label done, adapted; | 3480 Label done, adapted; |
3408 __ ldr(scratch, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3481 int fp_offset = StandardFrameConstants::kCallerFPOffset + fp_sp_delta_; |
| 3482 __ ldr(scratch, MemOperand(sp, fp_offset)); |
3409 __ ldr(result, MemOperand(scratch, StandardFrameConstants::kContextOffset)); | 3483 __ ldr(result, MemOperand(scratch, StandardFrameConstants::kContextOffset)); |
3410 __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); | 3484 __ cmp(result, Operand(Smi::FromInt(StackFrame::ARGUMENTS_ADAPTOR))); |
3411 | 3485 |
3412 // Result is the frame pointer for the frame if not adapted and for the real | 3486 // Result is the frame pointer for the frame if not adapted and for the real |
3413 // frame below the adaptor frame if adapted. | 3487 // frame below the adaptor frame if adapted. |
3414 __ mov(result, fp, LeaveCC, ne); | 3488 __ mov(result, fp, LeaveCC, ne); |
3415 __ mov(result, scratch, LeaveCC, eq); | 3489 __ mov(result, scratch, LeaveCC, eq); |
3416 } | 3490 } |
3417 } | 3491 } |
3418 | 3492 |
3419 | 3493 |
3420 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { | 3494 void LCodeGen::DoArgumentsLength(LArgumentsLength* instr) { |
3421 Register elem = ToRegister(instr->elements()); | 3495 Register elem = ToRegister(instr->elements()); |
3422 Register result = ToRegister(instr->result()); | 3496 Register result = ToRegister(instr->result()); |
3423 | 3497 |
3424 Label done; | 3498 Label done; |
3425 | 3499 |
3426 // If no arguments adaptor frame the number of arguments is fixed. | 3500 // If no arguments adaptor frame the number of arguments is fixed. |
3427 __ cmp(fp, elem); | 3501 __ cmp(fp, elem); |
3428 __ mov(result, Operand(scope()->num_parameters()), LeaveCC); | 3502 __ mov(result, Operand(scope()->num_parameters()), LeaveCC); |
3429 __ b(eq, &done); | 3503 __ b(eq, &done); |
3430 | 3504 |
3431 // Arguments adaptor frame present. Get argument length from there. | 3505 // Arguments adaptor frame present. Get argument length from there. |
3432 __ ldr(result, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 3506 int fp_offset = StandardFrameConstants::kCallerFPOffset + fp_sp_delta_; |
| 3507 __ ldr(result, MemOperand(sp, fp_offset)); |
3433 __ ldr(result, | 3508 __ ldr(result, |
3434 MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset)); | 3509 MemOperand(result, ArgumentsAdaptorFrameConstants::kLengthOffset)); |
3435 __ SmiUntag(result); | 3510 __ SmiUntag(result); |
3436 | 3511 |
3437 // Argument length is in result register. | 3512 // Argument length is in result register. |
3438 __ bind(&done); | 3513 __ bind(&done); |
3439 } | 3514 } |
3440 | 3515 |
3441 | 3516 |
3442 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { | 3517 void LCodeGen::DoWrapReceiver(LWrapReceiver* instr) { |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3525 ASSERT(instr->HasPointerMap()); | 3600 ASSERT(instr->HasPointerMap()); |
3526 LPointerMap* pointers = instr->pointer_map(); | 3601 LPointerMap* pointers = instr->pointer_map(); |
3527 RecordPosition(pointers->position()); | 3602 RecordPosition(pointers->position()); |
3528 SafepointGenerator safepoint_generator( | 3603 SafepointGenerator safepoint_generator( |
3529 this, pointers, Safepoint::kLazyDeopt); | 3604 this, pointers, Safepoint::kLazyDeopt); |
3530 // The number of arguments is stored in receiver which is r0, as expected | 3605 // The number of arguments is stored in receiver which is r0, as expected |
3531 // by InvokeFunction. | 3606 // by InvokeFunction. |
3532 ParameterCount actual(receiver); | 3607 ParameterCount actual(receiver); |
3533 __ InvokeFunction(function, actual, CALL_FUNCTION, | 3608 __ InvokeFunction(function, actual, CALL_FUNCTION, |
3534 safepoint_generator, CALL_AS_METHOD); | 3609 safepoint_generator, CALL_AS_METHOD); |
3535 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3610 int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_; |
| 3611 __ ldr(cp, MemOperand(sp, cp_offset)); |
3536 } | 3612 } |
3537 | 3613 |
3538 | 3614 |
3539 void LCodeGen::DoPushArgument(LPushArgument* instr) { | 3615 void LCodeGen::DoPushArgument(LPushArgument* instr) { |
3540 LOperand* argument = instr->value(); | 3616 LOperand* argument = instr->value(); |
3541 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { | 3617 if (argument->IsDoubleRegister() || argument->IsDoubleStackSlot()) { |
3542 Abort(kDoPushArgumentNotImplementedForDoubleType); | 3618 Abort(kDoPushArgumentNotImplementedForDoubleType); |
3543 } else { | 3619 } else { |
3544 Register argument_reg = EmitLoadRegister(argument, ip); | 3620 Register argument_reg = EmitLoadRegister(argument, ip); |
3545 __ push(argument_reg); | 3621 Push(argument_reg); |
3546 } | 3622 } |
3547 } | 3623 } |
3548 | 3624 |
3549 | 3625 |
3550 void LCodeGen::DoDrop(LDrop* instr) { | 3626 void LCodeGen::DoDrop(LDrop* instr) { |
3551 __ Drop(instr->count()); | 3627 __ Drop(instr->count()); |
| 3628 fp_sp_delta_ -= instr->count() * kPointerSize; |
3552 } | 3629 } |
3553 | 3630 |
3554 | 3631 |
3555 void LCodeGen::DoThisFunction(LThisFunction* instr) { | 3632 void LCodeGen::DoThisFunction(LThisFunction* instr) { |
3556 Register result = ToRegister(instr->result()); | 3633 Register result = ToRegister(instr->result()); |
3557 __ ldr(result, MemOperand(fp, JavaScriptFrameConstants::kFunctionOffset)); | 3634 int offset = JavaScriptFrameConstants::kFunctionOffset + fp_sp_delta_; |
| 3635 __ ldr(result, MemOperand(sp, offset)); |
3558 } | 3636 } |
3559 | 3637 |
3560 | 3638 |
3561 void LCodeGen::DoContext(LContext* instr) { | 3639 void LCodeGen::DoContext(LContext* instr) { |
3562 // If there is a non-return use, the context must be moved to a register. | 3640 // If there is a non-return use, the context must be moved to a register. |
3563 Register result = ToRegister(instr->result()); | 3641 Register result = ToRegister(instr->result()); |
3564 for (HUseIterator it(instr->hydrogen()->uses()); !it.Done(); it.Advance()) { | 3642 for (HUseIterator it(instr->hydrogen()->uses()); !it.Done(); it.Advance()) { |
3565 if (!it.value()->IsReturn()) { | 3643 if (!it.value()->IsReturn()) { |
3566 __ mov(result, cp); | 3644 __ mov(result, cp); |
3567 return; | 3645 return; |
3568 } | 3646 } |
3569 } | 3647 } |
3570 } | 3648 } |
3571 | 3649 |
3572 | 3650 |
3573 void LCodeGen::DoOuterContext(LOuterContext* instr) { | 3651 void LCodeGen::DoOuterContext(LOuterContext* instr) { |
3574 Register context = ToRegister(instr->context()); | 3652 Register context = ToRegister(instr->context()); |
3575 Register result = ToRegister(instr->result()); | 3653 Register result = ToRegister(instr->result()); |
3576 __ ldr(result, | 3654 __ ldr(result, |
3577 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); | 3655 MemOperand(context, Context::SlotOffset(Context::PREVIOUS_INDEX))); |
3578 } | 3656 } |
3579 | 3657 |
3580 | 3658 |
3581 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { | 3659 void LCodeGen::DoDeclareGlobals(LDeclareGlobals* instr) { |
3582 __ push(cp); // The context is the first argument. | 3660 Push(cp); // The context is the first argument. |
3583 __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs()); | 3661 __ LoadHeapObject(scratch0(), instr->hydrogen()->pairs()); |
3584 __ push(scratch0()); | 3662 Push(scratch0()); |
3585 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); | 3663 __ mov(scratch0(), Operand(Smi::FromInt(instr->hydrogen()->flags()))); |
3586 __ push(scratch0()); | 3664 Push(scratch0()); |
3587 CallRuntime(Runtime::kDeclareGlobals, 3, instr); | 3665 CallRuntime(Runtime::kDeclareGlobals, 3, instr); |
3588 } | 3666 } |
3589 | 3667 |
3590 | 3668 |
3591 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { | 3669 void LCodeGen::DoGlobalObject(LGlobalObject* instr) { |
3592 Register result = ToRegister(instr->result()); | 3670 Register result = ToRegister(instr->result()); |
3593 __ ldr(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); | 3671 __ ldr(result, ContextOperand(cp, Context::GLOBAL_OBJECT_INDEX)); |
3594 } | 3672 } |
3595 | 3673 |
3596 | 3674 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3636 | 3714 |
3637 // Set up deoptimization. | 3715 // Set up deoptimization. |
3638 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); | 3716 RecordSafepointWithLazyDeopt(instr, RECORD_SIMPLE_SAFEPOINT); |
3639 } else { | 3717 } else { |
3640 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 3718 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
3641 ParameterCount count(arity); | 3719 ParameterCount count(arity); |
3642 ParameterCount expected(formal_parameter_count); | 3720 ParameterCount expected(formal_parameter_count); |
3643 __ InvokeFunction( | 3721 __ InvokeFunction( |
3644 function, expected, count, CALL_FUNCTION, generator, call_kind); | 3722 function, expected, count, CALL_FUNCTION, generator, call_kind); |
3645 } | 3723 } |
| 3724 fp_sp_delta_ -= (arity + 1) * kPointerSize; |
3646 | 3725 |
3647 // Restore context. | 3726 // Restore context. |
3648 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 3727 int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_; |
| 3728 __ ldr(cp, MemOperand(sp, cp_offset)); |
3649 } | 3729 } |
3650 | 3730 |
3651 | 3731 |
3652 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { | 3732 void LCodeGen::DoCallConstantFunction(LCallConstantFunction* instr) { |
3653 ASSERT(ToRegister(instr->result()).is(r0)); | 3733 ASSERT(ToRegister(instr->result()).is(r0)); |
3654 CallKnownFunction(instr->hydrogen()->function(), | 3734 CallKnownFunction(instr->hydrogen()->function(), |
3655 instr->hydrogen()->formal_parameter_count(), | 3735 instr->hydrogen()->formal_parameter_count(), |
3656 instr->arity(), | 3736 instr->arity(), |
3657 instr, | 3737 instr, |
3658 CALL_AS_METHOD, | 3738 CALL_AS_METHOD, |
(...skipping 327 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3986 MathExpGenerator::EmitMathExp( | 4066 MathExpGenerator::EmitMathExp( |
3987 masm(), input, result, double_scratch1, double_scratch2, | 4067 masm(), input, result, double_scratch1, double_scratch2, |
3988 temp1, temp2, scratch0()); | 4068 temp1, temp2, scratch0()); |
3989 } | 4069 } |
3990 | 4070 |
3991 | 4071 |
3992 void LCodeGen::DoMathLog(LMathLog* instr) { | 4072 void LCodeGen::DoMathLog(LMathLog* instr) { |
3993 ASSERT(ToDoubleRegister(instr->result()).is(d2)); | 4073 ASSERT(ToDoubleRegister(instr->result()).is(d2)); |
3994 TranscendentalCacheStub stub(TranscendentalCache::LOG, | 4074 TranscendentalCacheStub stub(TranscendentalCache::LOG, |
3995 TranscendentalCacheStub::UNTAGGED); | 4075 TranscendentalCacheStub::UNTAGGED); |
3996 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4076 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr); |
3997 } | 4077 } |
3998 | 4078 |
3999 | 4079 |
4000 void LCodeGen::DoMathTan(LMathTan* instr) { | 4080 void LCodeGen::DoMathTan(LMathTan* instr) { |
4001 ASSERT(ToDoubleRegister(instr->result()).is(d2)); | 4081 ASSERT(ToDoubleRegister(instr->result()).is(d2)); |
4002 TranscendentalCacheStub stub(TranscendentalCache::TAN, | 4082 TranscendentalCacheStub stub(TranscendentalCache::TAN, |
4003 TranscendentalCacheStub::UNTAGGED); | 4083 TranscendentalCacheStub::UNTAGGED); |
4004 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4084 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr); |
4005 } | 4085 } |
4006 | 4086 |
4007 | 4087 |
4008 void LCodeGen::DoMathCos(LMathCos* instr) { | 4088 void LCodeGen::DoMathCos(LMathCos* instr) { |
4009 ASSERT(ToDoubleRegister(instr->result()).is(d2)); | 4089 ASSERT(ToDoubleRegister(instr->result()).is(d2)); |
4010 TranscendentalCacheStub stub(TranscendentalCache::COS, | 4090 TranscendentalCacheStub stub(TranscendentalCache::COS, |
4011 TranscendentalCacheStub::UNTAGGED); | 4091 TranscendentalCacheStub::UNTAGGED); |
4012 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4092 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr); |
4013 } | 4093 } |
4014 | 4094 |
4015 | 4095 |
4016 void LCodeGen::DoMathSin(LMathSin* instr) { | 4096 void LCodeGen::DoMathSin(LMathSin* instr) { |
4017 ASSERT(ToDoubleRegister(instr->result()).is(d2)); | 4097 ASSERT(ToDoubleRegister(instr->result()).is(d2)); |
4018 TranscendentalCacheStub stub(TranscendentalCache::SIN, | 4098 TranscendentalCacheStub stub(TranscendentalCache::SIN, |
4019 TranscendentalCacheStub::UNTAGGED); | 4099 TranscendentalCacheStub::UNTAGGED); |
4020 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4100 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr); |
4021 } | 4101 } |
4022 | 4102 |
4023 | 4103 |
4024 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { | 4104 void LCodeGen::DoInvokeFunction(LInvokeFunction* instr) { |
4025 ASSERT(ToRegister(instr->function()).is(r1)); | 4105 ASSERT(ToRegister(instr->function()).is(r1)); |
4026 ASSERT(instr->HasPointerMap()); | 4106 ASSERT(instr->HasPointerMap()); |
4027 | 4107 |
4028 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); | 4108 Handle<JSFunction> known_function = instr->hydrogen()->known_function(); |
4029 if (known_function.is_null()) { | 4109 if (known_function.is_null()) { |
4030 LPointerMap* pointers = instr->pointer_map(); | 4110 LPointerMap* pointers = instr->pointer_map(); |
4031 RecordPosition(pointers->position()); | 4111 RecordPosition(pointers->position()); |
4032 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); | 4112 SafepointGenerator generator(this, pointers, Safepoint::kLazyDeopt); |
4033 ParameterCount count(instr->arity()); | 4113 ParameterCount count(instr->arity()); |
4034 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); | 4114 __ InvokeFunction(r1, count, CALL_FUNCTION, generator, CALL_AS_METHOD); |
4035 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4115 fp_sp_delta_ -= (instr->arity() + 1) * kPointerSize; |
| 4116 int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_; |
| 4117 __ ldr(cp, MemOperand(sp, cp_offset)); |
4036 } else { | 4118 } else { |
4037 CallKnownFunction(known_function, | 4119 CallKnownFunction(known_function, |
4038 instr->hydrogen()->formal_parameter_count(), | 4120 instr->hydrogen()->formal_parameter_count(), |
4039 instr->arity(), | 4121 instr->arity(), |
4040 instr, | 4122 instr, |
4041 CALL_AS_METHOD, | 4123 CALL_AS_METHOD, |
4042 R1_CONTAINS_TARGET); | 4124 R1_CONTAINS_TARGET); |
4043 } | 4125 } |
4044 } | 4126 } |
4045 | 4127 |
4046 | 4128 |
4047 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { | 4129 void LCodeGen::DoCallKeyed(LCallKeyed* instr) { |
4048 ASSERT(ToRegister(instr->result()).is(r0)); | 4130 ASSERT(ToRegister(instr->result()).is(r0)); |
4049 | 4131 |
4050 int arity = instr->arity(); | 4132 int arity = instr->arity(); |
4051 Handle<Code> ic = | 4133 Handle<Code> ic = |
4052 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); | 4134 isolate()->stub_cache()->ComputeKeyedCallInitialize(arity); |
4053 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4135 CallCode(ic, RelocInfo::CODE_TARGET, arity + 1, instr, |
4054 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4136 NEVER_INLINE_TARGET_ADDRESS); |
| 4137 int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_; |
| 4138 __ ldr(cp, MemOperand(sp, cp_offset)); |
4055 } | 4139 } |
4056 | 4140 |
4057 | 4141 |
4058 void LCodeGen::DoCallNamed(LCallNamed* instr) { | 4142 void LCodeGen::DoCallNamed(LCallNamed* instr) { |
4059 ASSERT(ToRegister(instr->result()).is(r0)); | 4143 ASSERT(ToRegister(instr->result()).is(r0)); |
4060 | 4144 |
4061 int arity = instr->arity(); | 4145 int arity = instr->arity(); |
4062 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; | 4146 RelocInfo::Mode mode = RelocInfo::CODE_TARGET; |
4063 Handle<Code> ic = | 4147 Handle<Code> ic = |
4064 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4148 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
4065 __ mov(r2, Operand(instr->name())); | 4149 __ mov(r2, Operand(instr->name())); |
4066 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); | 4150 CallCode(ic, mode, arity + 1, instr, NEVER_INLINE_TARGET_ADDRESS); |
4067 // Restore context register. | 4151 // Restore context register. |
4068 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4152 int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_; |
| 4153 __ ldr(cp, MemOperand(sp, cp_offset)); |
4069 } | 4154 } |
4070 | 4155 |
4071 | 4156 |
4072 void LCodeGen::DoCallFunction(LCallFunction* instr) { | 4157 void LCodeGen::DoCallFunction(LCallFunction* instr) { |
4073 ASSERT(ToRegister(instr->function()).is(r1)); | 4158 ASSERT(ToRegister(instr->function()).is(r1)); |
4074 ASSERT(ToRegister(instr->result()).is(r0)); | 4159 ASSERT(ToRegister(instr->result()).is(r0)); |
4075 | 4160 |
4076 int arity = instr->arity(); | 4161 int arity = instr->arity(); |
4077 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); | 4162 CallFunctionStub stub(arity, NO_CALL_FUNCTION_FLAGS); |
4078 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4163 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, arity + 1, instr); |
4079 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4164 int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_; |
| 4165 __ ldr(cp, MemOperand(sp, cp_offset)); |
4080 } | 4166 } |
4081 | 4167 |
4082 | 4168 |
4083 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { | 4169 void LCodeGen::DoCallGlobal(LCallGlobal* instr) { |
4084 ASSERT(ToRegister(instr->result()).is(r0)); | 4170 ASSERT(ToRegister(instr->result()).is(r0)); |
4085 | 4171 |
4086 int arity = instr->arity(); | 4172 int arity = instr->arity(); |
4087 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; | 4173 RelocInfo::Mode mode = RelocInfo::CODE_TARGET_CONTEXT; |
4088 Handle<Code> ic = | 4174 Handle<Code> ic = |
4089 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); | 4175 isolate()->stub_cache()->ComputeCallInitialize(arity, mode); |
4090 __ mov(r2, Operand(instr->name())); | 4176 __ mov(r2, Operand(instr->name())); |
4091 CallCode(ic, mode, instr, NEVER_INLINE_TARGET_ADDRESS); | 4177 CallCode(ic, mode, arity + 1, instr, NEVER_INLINE_TARGET_ADDRESS); |
4092 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); | 4178 int cp_offset = StandardFrameConstants::kContextOffset + fp_sp_delta_; |
| 4179 __ ldr(cp, MemOperand(sp, cp_offset)); |
4093 } | 4180 } |
4094 | 4181 |
4095 | 4182 |
4096 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { | 4183 void LCodeGen::DoCallKnownGlobal(LCallKnownGlobal* instr) { |
4097 ASSERT(ToRegister(instr->result()).is(r0)); | 4184 ASSERT(ToRegister(instr->result()).is(r0)); |
4098 CallKnownFunction(instr->hydrogen()->target(), | 4185 CallKnownFunction(instr->hydrogen()->target(), |
4099 instr->hydrogen()->formal_parameter_count(), | 4186 instr->hydrogen()->formal_parameter_count(), |
4100 instr->arity(), | 4187 instr->arity(), |
4101 instr, | 4188 instr, |
4102 CALL_AS_FUNCTION, | 4189 CALL_AS_FUNCTION, |
4103 R1_UNINITIALIZED); | 4190 R1_UNINITIALIZED); |
4104 } | 4191 } |
4105 | 4192 |
4106 | 4193 |
4107 void LCodeGen::DoCallNew(LCallNew* instr) { | 4194 void LCodeGen::DoCallNew(LCallNew* instr) { |
4108 ASSERT(ToRegister(instr->constructor()).is(r1)); | 4195 ASSERT(ToRegister(instr->constructor()).is(r1)); |
4109 ASSERT(ToRegister(instr->result()).is(r0)); | 4196 ASSERT(ToRegister(instr->result()).is(r0)); |
4110 | 4197 |
4111 __ mov(r0, Operand(instr->arity())); | 4198 __ mov(r0, Operand(instr->arity())); |
4112 // No cell in r2 for construct type feedback in optimized code | 4199 // No cell in r2 for construct type feedback in optimized code |
4113 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); | 4200 Handle<Object> undefined_value(isolate()->factory()->undefined_value()); |
4114 __ mov(r2, Operand(undefined_value)); | 4201 __ mov(r2, Operand(undefined_value)); |
4115 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); | 4202 CallConstructStub stub(NO_CALL_FUNCTION_FLAGS); |
4116 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4203 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, |
| 4204 instr->arity() + 1, instr); |
4117 } | 4205 } |
4118 | 4206 |
4119 | 4207 |
4120 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { | 4208 void LCodeGen::DoCallNewArray(LCallNewArray* instr) { |
4121 ASSERT(ToRegister(instr->constructor()).is(r1)); | 4209 ASSERT(ToRegister(instr->constructor()).is(r1)); |
4122 ASSERT(ToRegister(instr->result()).is(r0)); | 4210 ASSERT(ToRegister(instr->result()).is(r0)); |
4123 | 4211 |
4124 __ mov(r0, Operand(instr->arity())); | 4212 __ mov(r0, Operand(instr->arity())); |
4125 __ mov(r2, Operand(instr->hydrogen()->property_cell())); | 4213 __ mov(r2, Operand(instr->hydrogen()->property_cell())); |
4126 ElementsKind kind = instr->hydrogen()->elements_kind(); | 4214 ElementsKind kind = instr->hydrogen()->elements_kind(); |
4127 AllocationSiteOverrideMode override_mode = | 4215 AllocationSiteOverrideMode override_mode = |
4128 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) | 4216 (AllocationSite::GetMode(kind) == TRACK_ALLOCATION_SITE) |
4129 ? DISABLE_ALLOCATION_SITES | 4217 ? DISABLE_ALLOCATION_SITES |
4130 : DONT_OVERRIDE; | 4218 : DONT_OVERRIDE; |
4131 ContextCheckMode context_mode = CONTEXT_CHECK_NOT_REQUIRED; | 4219 ContextCheckMode context_mode = CONTEXT_CHECK_NOT_REQUIRED; |
4132 | 4220 |
4133 if (instr->arity() == 0) { | 4221 if (instr->arity() == 0) { |
4134 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); | 4222 ArrayNoArgumentConstructorStub stub(kind, context_mode, override_mode); |
4135 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4223 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, |
| 4224 instr->arity() + 1, instr); |
4136 } else if (instr->arity() == 1) { | 4225 } else if (instr->arity() == 1) { |
4137 Label done; | 4226 Label done; |
4138 if (IsFastPackedElementsKind(kind)) { | 4227 if (IsFastPackedElementsKind(kind)) { |
4139 Label packed_case; | 4228 Label packed_case; |
4140 // We might need a change here | 4229 // We might need a change here |
4141 // look at the first argument | 4230 // look at the first argument |
4142 __ ldr(r5, MemOperand(sp, 0)); | 4231 __ ldr(r5, MemOperand(sp, 0)); |
4143 __ cmp(r5, Operand::Zero()); | 4232 __ cmp(r5, Operand::Zero()); |
4144 __ b(eq, &packed_case); | 4233 __ b(eq, &packed_case); |
4145 | 4234 |
4146 ElementsKind holey_kind = GetHoleyElementsKind(kind); | 4235 ElementsKind holey_kind = GetHoleyElementsKind(kind); |
4147 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, | 4236 ArraySingleArgumentConstructorStub stub(holey_kind, context_mode, |
4148 override_mode); | 4237 override_mode); |
4149 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4238 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, |
| 4239 instr->arity() + 1, instr); |
4150 __ jmp(&done); | 4240 __ jmp(&done); |
4151 __ bind(&packed_case); | 4241 __ bind(&packed_case); |
| 4242 fp_sp_delta_ += (instr->arity() + 1) * kPointerSize; |
4152 } | 4243 } |
4153 | 4244 |
4154 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); | 4245 ArraySingleArgumentConstructorStub stub(kind, context_mode, override_mode); |
4155 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4246 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, |
| 4247 instr->arity() + 1, instr); |
4156 __ bind(&done); | 4248 __ bind(&done); |
4157 } else { | 4249 } else { |
4158 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); | 4250 ArrayNArgumentsConstructorStub stub(kind, context_mode, override_mode); |
4159 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, instr); | 4251 CallCode(stub.GetCode(isolate()), RelocInfo::CONSTRUCT_CALL, |
| 4252 instr->arity() + 1, instr); |
4160 } | 4253 } |
4161 } | 4254 } |
4162 | 4255 |
4163 | 4256 |
4164 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { | 4257 void LCodeGen::DoCallRuntime(LCallRuntime* instr) { |
4165 CallRuntime(instr->function(), instr->arity(), instr); | 4258 CallRuntime(instr->function(), instr->arity(), instr); |
4166 } | 4259 } |
4167 | 4260 |
4168 | 4261 |
4169 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { | 4262 void LCodeGen::DoInnerAllocatedObject(LInnerAllocatedObject* instr) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4261 | 4354 |
4262 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { | 4355 void LCodeGen::DoStoreNamedGeneric(LStoreNamedGeneric* instr) { |
4263 ASSERT(ToRegister(instr->object()).is(r1)); | 4356 ASSERT(ToRegister(instr->object()).is(r1)); |
4264 ASSERT(ToRegister(instr->value()).is(r0)); | 4357 ASSERT(ToRegister(instr->value()).is(r0)); |
4265 | 4358 |
4266 // Name is always in r2. | 4359 // Name is always in r2. |
4267 __ mov(r2, Operand(instr->name())); | 4360 __ mov(r2, Operand(instr->name())); |
4268 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4361 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
4269 ? isolate()->builtins()->StoreIC_Initialize_Strict() | 4362 ? isolate()->builtins()->StoreIC_Initialize_Strict() |
4270 : isolate()->builtins()->StoreIC_Initialize(); | 4363 : isolate()->builtins()->StoreIC_Initialize(); |
4271 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4364 CallCode(ic, RelocInfo::CODE_TARGET, 0, instr, NEVER_INLINE_TARGET_ADDRESS); |
4272 } | 4365 } |
4273 | 4366 |
4274 | 4367 |
4275 void LCodeGen::ApplyCheckIf(Condition condition, LBoundsCheck* check) { | 4368 void LCodeGen::ApplyCheckIf(Condition condition, LBoundsCheck* check) { |
4276 if (FLAG_debug_code && check->hydrogen()->skip_check()) { | 4369 if (FLAG_debug_code && check->hydrogen()->skip_check()) { |
4277 Label done; | 4370 Label done; |
4278 __ b(NegateCondition(condition), &done); | 4371 __ b(NegateCondition(condition), &done); |
4279 __ stop("eliminated bounds check failed"); | 4372 __ stop("eliminated bounds check failed"); |
4280 __ bind(&done); | 4373 __ bind(&done); |
4281 } else { | 4374 } else { |
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
4477 | 4570 |
4478 | 4571 |
4479 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { | 4572 void LCodeGen::DoStoreKeyedGeneric(LStoreKeyedGeneric* instr) { |
4480 ASSERT(ToRegister(instr->object()).is(r2)); | 4573 ASSERT(ToRegister(instr->object()).is(r2)); |
4481 ASSERT(ToRegister(instr->key()).is(r1)); | 4574 ASSERT(ToRegister(instr->key()).is(r1)); |
4482 ASSERT(ToRegister(instr->value()).is(r0)); | 4575 ASSERT(ToRegister(instr->value()).is(r0)); |
4483 | 4576 |
4484 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) | 4577 Handle<Code> ic = (instr->strict_mode_flag() == kStrictMode) |
4485 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() | 4578 ? isolate()->builtins()->KeyedStoreIC_Initialize_Strict() |
4486 : isolate()->builtins()->KeyedStoreIC_Initialize(); | 4579 : isolate()->builtins()->KeyedStoreIC_Initialize(); |
4487 CallCode(ic, RelocInfo::CODE_TARGET, instr, NEVER_INLINE_TARGET_ADDRESS); | 4580 CallCode(ic, RelocInfo::CODE_TARGET, 0, instr, NEVER_INLINE_TARGET_ADDRESS); |
4488 } | 4581 } |
4489 | 4582 |
4490 | 4583 |
4491 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { | 4584 void LCodeGen::DoTransitionElementsKind(LTransitionElementsKind* instr) { |
4492 Register object_reg = ToRegister(instr->object()); | 4585 Register object_reg = ToRegister(instr->object()); |
4493 Register scratch = scratch0(); | 4586 Register scratch = scratch0(); |
4494 | 4587 |
4495 Handle<Map> from_map = instr->original_map(); | 4588 Handle<Map> from_map = instr->original_map(); |
4496 Handle<Map> to_map = instr->transitioned_map(); | 4589 Handle<Map> to_map = instr->transitioned_map(); |
4497 ElementsKind from_kind = instr->from_kind(); | 4590 ElementsKind from_kind = instr->from_kind(); |
(...skipping 27 matching lines...) Expand all Loading... |
4525 | 4618 |
4526 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { | 4619 void LCodeGen::DoTrapAllocationMemento(LTrapAllocationMemento* instr) { |
4527 Register object = ToRegister(instr->object()); | 4620 Register object = ToRegister(instr->object()); |
4528 Register temp = ToRegister(instr->temp()); | 4621 Register temp = ToRegister(instr->temp()); |
4529 __ TestJSArrayForAllocationMemento(object, temp); | 4622 __ TestJSArrayForAllocationMemento(object, temp); |
4530 DeoptimizeIf(eq, instr->environment()); | 4623 DeoptimizeIf(eq, instr->environment()); |
4531 } | 4624 } |
4532 | 4625 |
4533 | 4626 |
4534 void LCodeGen::DoStringAdd(LStringAdd* instr) { | 4627 void LCodeGen::DoStringAdd(LStringAdd* instr) { |
4535 __ push(ToRegister(instr->left())); | 4628 Push(ToRegister(instr->left())); |
4536 __ push(ToRegister(instr->right())); | 4629 Push(ToRegister(instr->right())); |
4537 StringAddStub stub(instr->hydrogen()->flags()); | 4630 StringAddStub stub(instr->hydrogen()->flags()); |
4538 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 4631 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 2, instr); |
4539 } | 4632 } |
4540 | 4633 |
4541 | 4634 |
4542 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { | 4635 void LCodeGen::DoStringCharCodeAt(LStringCharCodeAt* instr) { |
4543 class DeferredStringCharCodeAt: public LDeferredCode { | 4636 class DeferredStringCharCodeAt: public LDeferredCode { |
4544 public: | 4637 public: |
4545 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) | 4638 DeferredStringCharCodeAt(LCodeGen* codegen, LStringCharCodeAt* instr) |
4546 : LDeferredCode(codegen), instr_(instr) { } | 4639 : LDeferredCode(codegen), instr_(instr) { } |
4547 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } | 4640 virtual void Generate() { codegen()->DoDeferredStringCharCodeAt(instr_); } |
4548 virtual LInstruction* instr() { return instr_; } | 4641 virtual LInstruction* instr() { return instr_; } |
(...skipping 17 matching lines...) Expand all Loading... |
4566 Register string = ToRegister(instr->string()); | 4659 Register string = ToRegister(instr->string()); |
4567 Register result = ToRegister(instr->result()); | 4660 Register result = ToRegister(instr->result()); |
4568 Register scratch = scratch0(); | 4661 Register scratch = scratch0(); |
4569 | 4662 |
4570 // TODO(3095996): Get rid of this. For now, we need to make the | 4663 // TODO(3095996): Get rid of this. For now, we need to make the |
4571 // result register contain a valid pointer because it is already | 4664 // result register contain a valid pointer because it is already |
4572 // contained in the register pointer map. | 4665 // contained in the register pointer map. |
4573 __ mov(result, Operand::Zero()); | 4666 __ mov(result, Operand::Zero()); |
4574 | 4667 |
4575 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4668 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4576 __ push(string); | 4669 Push(string); |
4577 // Push the index as a smi. This is safe because of the checks in | 4670 // Push the index as a smi. This is safe because of the checks in |
4578 // DoStringCharCodeAt above. | 4671 // DoStringCharCodeAt above. |
4579 if (instr->index()->IsConstantOperand()) { | 4672 if (instr->index()->IsConstantOperand()) { |
4580 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); | 4673 int const_index = ToInteger32(LConstantOperand::cast(instr->index())); |
4581 __ mov(scratch, Operand(Smi::FromInt(const_index))); | 4674 __ mov(scratch, Operand(Smi::FromInt(const_index))); |
4582 __ push(scratch); | 4675 Push(scratch); |
4583 } else { | 4676 } else { |
4584 Register index = ToRegister(instr->index()); | 4677 Register index = ToRegister(instr->index()); |
4585 __ SmiTag(index); | 4678 __ SmiTag(index); |
4586 __ push(index); | 4679 Push(index); |
4587 } | 4680 } |
4588 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); | 4681 CallRuntimeFromDeferred(Runtime::kStringCharCodeAt, 2, instr); |
4589 __ AssertSmi(r0); | 4682 __ AssertSmi(r0); |
4590 __ SmiUntag(r0); | 4683 __ SmiUntag(r0); |
4591 __ StoreToSafepointRegisterSlot(r0, result); | 4684 __ StoreToSafepointRegisterSlot(r0, result); |
4592 } | 4685 } |
4593 | 4686 |
4594 | 4687 |
4595 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { | 4688 void LCodeGen::DoStringCharFromCode(LStringCharFromCode* instr) { |
4596 class DeferredStringCharFromCode: public LDeferredCode { | 4689 class DeferredStringCharFromCode: public LDeferredCode { |
(...skipping 30 matching lines...) Expand all Loading... |
4627 Register char_code = ToRegister(instr->char_code()); | 4720 Register char_code = ToRegister(instr->char_code()); |
4628 Register result = ToRegister(instr->result()); | 4721 Register result = ToRegister(instr->result()); |
4629 | 4722 |
4630 // TODO(3095996): Get rid of this. For now, we need to make the | 4723 // TODO(3095996): Get rid of this. For now, we need to make the |
4631 // result register contain a valid pointer because it is already | 4724 // result register contain a valid pointer because it is already |
4632 // contained in the register pointer map. | 4725 // contained in the register pointer map. |
4633 __ mov(result, Operand::Zero()); | 4726 __ mov(result, Operand::Zero()); |
4634 | 4727 |
4635 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 4728 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
4636 __ SmiTag(char_code); | 4729 __ SmiTag(char_code); |
4637 __ push(char_code); | 4730 Push(char_code); |
4638 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); | 4731 CallRuntimeFromDeferred(Runtime::kCharFromCode, 1, instr); |
4639 __ StoreToSafepointRegisterSlot(r0, result); | 4732 __ StoreToSafepointRegisterSlot(r0, result); |
4640 } | 4733 } |
4641 | 4734 |
4642 | 4735 |
4643 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { | 4736 void LCodeGen::DoInteger32ToDouble(LInteger32ToDouble* instr) { |
4644 LOperand* input = instr->value(); | 4737 LOperand* input = instr->value(); |
4645 ASSERT(input->IsRegister() || input->IsStackSlot()); | 4738 ASSERT(input->IsRegister() || input->IsStackSlot()); |
4646 LOperand* output = instr->result(); | 4739 LOperand* output = instr->result(); |
4647 ASSERT(output->IsDoubleRegister()); | 4740 ASSERT(output->IsDoubleRegister()); |
(...skipping 710 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5358 // TODO(3095996): Get rid of this. For now, we need to make the | 5451 // TODO(3095996): Get rid of this. For now, we need to make the |
5359 // result register contain a valid pointer because it is already | 5452 // result register contain a valid pointer because it is already |
5360 // contained in the register pointer map. | 5453 // contained in the register pointer map. |
5361 __ mov(result, Operand(Smi::FromInt(0))); | 5454 __ mov(result, Operand(Smi::FromInt(0))); |
5362 | 5455 |
5363 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); | 5456 PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); |
5364 if (instr->size()->IsRegister()) { | 5457 if (instr->size()->IsRegister()) { |
5365 Register size = ToRegister(instr->size()); | 5458 Register size = ToRegister(instr->size()); |
5366 ASSERT(!size.is(result)); | 5459 ASSERT(!size.is(result)); |
5367 __ SmiTag(size); | 5460 __ SmiTag(size); |
5368 __ push(size); | 5461 Push(size); |
5369 } else { | 5462 } else { |
5370 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); | 5463 int32_t size = ToInteger32(LConstantOperand::cast(instr->size())); |
5371 __ Push(Smi::FromInt(size)); | 5464 __ Push(Smi::FromInt(size)); |
5372 } | 5465 } |
5373 | 5466 |
5374 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { | 5467 if (instr->hydrogen()->IsOldPointerSpaceAllocation()) { |
5375 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); | 5468 ASSERT(!instr->hydrogen()->IsOldDataSpaceAllocation()); |
5376 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5469 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
5377 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); | 5470 CallRuntimeFromDeferred(Runtime::kAllocateInOldPointerSpace, 1, instr); |
5378 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { | 5471 } else if (instr->hydrogen()->IsOldDataSpaceAllocation()) { |
5379 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); | 5472 ASSERT(!instr->hydrogen()->IsNewSpaceAllocation()); |
5380 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); | 5473 CallRuntimeFromDeferred(Runtime::kAllocateInOldDataSpace, 1, instr); |
5381 } else { | 5474 } else { |
5382 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); | 5475 CallRuntimeFromDeferred(Runtime::kAllocateInNewSpace, 1, instr); |
5383 } | 5476 } |
5384 __ StoreToSafepointRegisterSlot(r0, result); | 5477 __ StoreToSafepointRegisterSlot(r0, result); |
5385 } | 5478 } |
5386 | 5479 |
5387 | 5480 |
5388 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { | 5481 void LCodeGen::DoToFastProperties(LToFastProperties* instr) { |
5389 ASSERT(ToRegister(instr->value()).is(r0)); | 5482 ASSERT(ToRegister(instr->value()).is(r0)); |
5390 __ push(r0); | 5483 Push(r0); |
5391 CallRuntime(Runtime::kToFastProperties, 1, instr); | 5484 CallRuntime(Runtime::kToFastProperties, 1, instr); |
5392 } | 5485 } |
5393 | 5486 |
5394 | 5487 |
5395 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { | 5488 void LCodeGen::DoRegExpLiteral(LRegExpLiteral* instr) { |
5396 Label materialized; | 5489 Label materialized; |
5397 // Registers will be used as follows: | 5490 // Registers will be used as follows: |
5398 // r7 = literals array. | 5491 // r7 = literals array. |
5399 // r1 = regexp literal. | 5492 // r1 = regexp literal. |
5400 // r0 = regexp literal clone. | 5493 // r0 = regexp literal clone. |
5401 // r2 and r4-r6 are used as temporaries. | 5494 // r2 and r4-r6 are used as temporaries. |
5402 int literal_offset = | 5495 int literal_offset = |
5403 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); | 5496 FixedArray::OffsetOfElementAt(instr->hydrogen()->literal_index()); |
5404 __ LoadHeapObject(r7, instr->hydrogen()->literals()); | 5497 __ LoadHeapObject(r7, instr->hydrogen()->literals()); |
5405 __ ldr(r1, FieldMemOperand(r7, literal_offset)); | 5498 __ ldr(r1, FieldMemOperand(r7, literal_offset)); |
5406 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); | 5499 __ LoadRoot(ip, Heap::kUndefinedValueRootIndex); |
5407 __ cmp(r1, ip); | 5500 __ cmp(r1, ip); |
5408 __ b(ne, &materialized); | 5501 __ b(ne, &materialized); |
5409 | 5502 |
5410 // Create regexp literal using runtime function | 5503 // Create regexp literal using runtime function |
5411 // Result will be in r0. | 5504 // Result will be in r0. |
5412 __ mov(r6, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); | 5505 __ mov(r6, Operand(Smi::FromInt(instr->hydrogen()->literal_index()))); |
5413 __ mov(r5, Operand(instr->hydrogen()->pattern())); | 5506 __ mov(r5, Operand(instr->hydrogen()->pattern())); |
5414 __ mov(r4, Operand(instr->hydrogen()->flags())); | 5507 __ mov(r4, Operand(instr->hydrogen()->flags())); |
5415 __ Push(r7, r6, r5, r4); | 5508 Push(r7, r6, r5, r4); |
5416 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); | 5509 CallRuntime(Runtime::kMaterializeRegExpLiteral, 4, instr); |
5417 __ mov(r1, r0); | 5510 __ mov(r1, r0); |
5418 | 5511 |
5419 __ bind(&materialized); | 5512 __ bind(&materialized); |
5420 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; | 5513 int size = JSRegExp::kSize + JSRegExp::kInObjectFieldCount * kPointerSize; |
5421 Label allocated, runtime_allocate; | 5514 Label allocated, runtime_allocate; |
5422 | 5515 |
5423 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); | 5516 __ Allocate(size, r0, r2, r3, &runtime_allocate, TAG_OBJECT); |
5424 __ jmp(&allocated); | 5517 __ jmp(&allocated); |
5425 | 5518 |
5426 __ bind(&runtime_allocate); | 5519 __ bind(&runtime_allocate); |
5427 __ mov(r0, Operand(Smi::FromInt(size))); | 5520 __ mov(r0, Operand(Smi::FromInt(size))); |
5428 __ Push(r1, r0); | 5521 Push(r1, r0); |
5429 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); | 5522 CallRuntime(Runtime::kAllocateInNewSpace, 1, instr); |
5430 __ pop(r1); | 5523 __ pop(r1); |
| 5524 fp_sp_delta_ -= kPointerSize; |
5431 | 5525 |
5432 __ bind(&allocated); | 5526 __ bind(&allocated); |
5433 // Copy the content into the newly allocated memory. | 5527 // Copy the content into the newly allocated memory. |
5434 __ CopyFields(r0, r1, double_scratch0(), size / kPointerSize); | 5528 __ CopyFields(r0, r1, double_scratch0(), size / kPointerSize); |
5435 } | 5529 } |
5436 | 5530 |
5437 | 5531 |
5438 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { | 5532 void LCodeGen::DoFunctionLiteral(LFunctionLiteral* instr) { |
5439 // Use the fast case closure allocation code that allocates in new | 5533 // Use the fast case closure allocation code that allocates in new |
5440 // space for nested functions that don't need literals cloning. | 5534 // space for nested functions that don't need literals cloning. |
5441 bool pretenure = instr->hydrogen()->pretenure(); | 5535 bool pretenure = instr->hydrogen()->pretenure(); |
5442 if (!pretenure && instr->hydrogen()->has_no_literals()) { | 5536 if (!pretenure && instr->hydrogen()->has_no_literals()) { |
5443 FastNewClosureStub stub(instr->hydrogen()->language_mode(), | 5537 FastNewClosureStub stub(instr->hydrogen()->language_mode(), |
5444 instr->hydrogen()->is_generator()); | 5538 instr->hydrogen()->is_generator()); |
5445 __ mov(r1, Operand(instr->hydrogen()->shared_info())); | 5539 __ mov(r1, Operand(instr->hydrogen()->shared_info())); |
5446 __ push(r1); | 5540 Push(r1); |
5447 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 5541 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 1, instr); |
5448 } else { | 5542 } else { |
5449 __ mov(r2, Operand(instr->hydrogen()->shared_info())); | 5543 __ mov(r2, Operand(instr->hydrogen()->shared_info())); |
5450 __ mov(r1, Operand(pretenure ? factory()->true_value() | 5544 __ mov(r1, Operand(pretenure ? factory()->true_value() |
5451 : factory()->false_value())); | 5545 : factory()->false_value())); |
5452 __ Push(cp, r2, r1); | 5546 Push(cp, r2, r1); |
5453 CallRuntime(Runtime::kNewClosure, 3, instr); | 5547 CallRuntime(Runtime::kNewClosure, 3, instr); |
5454 } | 5548 } |
5455 } | 5549 } |
5456 | 5550 |
5457 | 5551 |
5458 void LCodeGen::DoTypeof(LTypeof* instr) { | 5552 void LCodeGen::DoTypeof(LTypeof* instr) { |
5459 Register input = ToRegister(instr->value()); | 5553 Register input = ToRegister(instr->value()); |
5460 __ push(input); | 5554 Push(input); |
5461 CallRuntime(Runtime::kTypeof, 1, instr); | 5555 CallRuntime(Runtime::kTypeof, 1, instr); |
5462 } | 5556 } |
5463 | 5557 |
5464 | 5558 |
5465 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { | 5559 void LCodeGen::DoTypeofIsAndBranch(LTypeofIsAndBranch* instr) { |
5466 Register input = ToRegister(instr->value()); | 5560 Register input = ToRegister(instr->value()); |
5467 | 5561 |
5468 Condition final_branch_condition = EmitTypeofIs(instr->TrueLabel(chunk_), | 5562 Condition final_branch_condition = EmitTypeofIs(instr->TrueLabel(chunk_), |
5469 instr->FalseLabel(chunk_), | 5563 instr->FalseLabel(chunk_), |
5470 input, | 5564 input, |
(...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5655 // There is no LLazyBailout instruction for stack-checks. We have to | 5749 // There is no LLazyBailout instruction for stack-checks. We have to |
5656 // prepare for lazy deoptimization explicitly here. | 5750 // prepare for lazy deoptimization explicitly here. |
5657 if (instr->hydrogen()->is_function_entry()) { | 5751 if (instr->hydrogen()->is_function_entry()) { |
5658 // Perform stack overflow check. | 5752 // Perform stack overflow check. |
5659 Label done; | 5753 Label done; |
5660 __ LoadRoot(ip, Heap::kStackLimitRootIndex); | 5754 __ LoadRoot(ip, Heap::kStackLimitRootIndex); |
5661 __ cmp(sp, Operand(ip)); | 5755 __ cmp(sp, Operand(ip)); |
5662 __ b(hs, &done); | 5756 __ b(hs, &done); |
5663 StackCheckStub stub; | 5757 StackCheckStub stub; |
5664 PredictableCodeSizeScope predictable(masm_, 2 * Assembler::kInstrSize); | 5758 PredictableCodeSizeScope predictable(masm_, 2 * Assembler::kInstrSize); |
5665 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, instr); | 5759 CallCode(stub.GetCode(isolate()), RelocInfo::CODE_TARGET, 0, instr); |
5666 EnsureSpaceForLazyDeopt(); | 5760 EnsureSpaceForLazyDeopt(); |
5667 last_lazy_deopt_pc_ = masm()->pc_offset(); | 5761 last_lazy_deopt_pc_ = masm()->pc_offset(); |
5668 __ bind(&done); | 5762 __ bind(&done); |
5669 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); | 5763 RegisterEnvironmentForDeoptimization(env, Safepoint::kLazyDeopt); |
5670 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); | 5764 safepoints_.RecordLazyDeoptimizationIndex(env->deoptimization_index()); |
5671 } else { | 5765 } else { |
5672 ASSERT(instr->hydrogen()->is_backwards_branch()); | 5766 ASSERT(instr->hydrogen()->is_backwards_branch()); |
5673 // Perform stack overflow check if this goto needs it before jumping. | 5767 // Perform stack overflow check if this goto needs it before jumping. |
5674 DeferredStackCheck* deferred_stack_check = | 5768 DeferredStackCheck* deferred_stack_check = |
5675 new(zone()) DeferredStackCheck(this, instr); | 5769 new(zone()) DeferredStackCheck(this, instr); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5723 DeoptimizeIf(le, instr->environment()); | 5817 DeoptimizeIf(le, instr->environment()); |
5724 | 5818 |
5725 Label use_cache, call_runtime; | 5819 Label use_cache, call_runtime; |
5726 __ CheckEnumCache(null_value, &call_runtime); | 5820 __ CheckEnumCache(null_value, &call_runtime); |
5727 | 5821 |
5728 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5822 __ ldr(r0, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5729 __ b(&use_cache); | 5823 __ b(&use_cache); |
5730 | 5824 |
5731 // Get the set of properties to enumerate. | 5825 // Get the set of properties to enumerate. |
5732 __ bind(&call_runtime); | 5826 __ bind(&call_runtime); |
5733 __ push(r0); | 5827 Push(r0); |
5734 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); | 5828 CallRuntime(Runtime::kGetPropertyNamesFast, 1, instr); |
5735 | 5829 |
5736 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); | 5830 __ ldr(r1, FieldMemOperand(r0, HeapObject::kMapOffset)); |
5737 __ LoadRoot(ip, Heap::kMetaMapRootIndex); | 5831 __ LoadRoot(ip, Heap::kMetaMapRootIndex); |
5738 __ cmp(r1, ip); | 5832 __ cmp(r1, ip); |
5739 DeoptimizeIf(ne, instr->environment()); | 5833 DeoptimizeIf(ne, instr->environment()); |
5740 __ bind(&use_cache); | 5834 __ bind(&use_cache); |
5741 } | 5835 } |
5742 | 5836 |
5743 | 5837 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
5795 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); | 5889 __ sub(scratch, result, Operand::PointerOffsetFromSmiKey(index)); |
5796 __ ldr(result, FieldMemOperand(scratch, | 5890 __ ldr(result, FieldMemOperand(scratch, |
5797 FixedArray::kHeaderSize - kPointerSize)); | 5891 FixedArray::kHeaderSize - kPointerSize)); |
5798 __ bind(&done); | 5892 __ bind(&done); |
5799 } | 5893 } |
5800 | 5894 |
5801 | 5895 |
5802 #undef __ | 5896 #undef __ |
5803 | 5897 |
5804 } } // namespace v8::internal | 5898 } } // namespace v8::internal |
OLD | NEW |