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 289 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
300 if (value == 1) return i; | 300 if (value == 1) return i; |
301 } | 301 } |
302 } | 302 } |
303 UNREACHABLE(); | 303 UNREACHABLE(); |
304 return -1; | 304 return -1; |
305 } | 305 } |
306 | 306 |
307 | 307 |
308 void Deoptimizer::DoComputeOsrOutputFrame() { | 308 void Deoptimizer::DoComputeOsrOutputFrame() { |
309 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 309 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
310 compiled_code_->deoptimization_data()); | 310 optimized_code_->deoptimization_data()); |
311 unsigned ast_id = data->OsrAstId()->value(); | 311 unsigned ast_id = data->OsrAstId()->value(); |
312 // TODO(kasperl): This should not be the bailout_id_. It should be | 312 // TODO(kasperl): This should not be the bailout_id_. It should be |
313 // the ast id. Confusing. | 313 // the ast id. Confusing. |
314 ASSERT(bailout_id_ == ast_id); | 314 ASSERT(bailout_id_ == ast_id); |
315 | 315 |
316 int bailout_id = LookupBailoutId(data, BailoutId(ast_id)); | 316 int bailout_id = LookupBailoutId(data, BailoutId(ast_id)); |
317 unsigned translation_index = data->TranslationIndex(bailout_id)->value(); | 317 unsigned translation_index = data->TranslationIndex(bailout_id)->value(); |
318 ByteArray* translations = data->TranslationByteArray(); | 318 ByteArray* translations = data->TranslationByteArray(); |
319 | 319 |
320 TranslationIterator iterator(translations, translation_index); | 320 TranslationIterator iterator(translations, translation_index); |
(...skipping 16 matching lines...) Expand all Loading... |
337 USE(closure_id); | 337 USE(closure_id); |
338 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); | 338 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); |
339 unsigned height = iterator.Next(); | 339 unsigned height = iterator.Next(); |
340 unsigned height_in_bytes = height * kPointerSize; | 340 unsigned height_in_bytes = height * kPointerSize; |
341 USE(height_in_bytes); | 341 USE(height_in_bytes); |
342 | 342 |
343 unsigned fixed_size = ComputeFixedSize(function_); | 343 unsigned fixed_size = ComputeFixedSize(function_); |
344 unsigned input_frame_size = input_->GetFrameSize(); | 344 unsigned input_frame_size = input_->GetFrameSize(); |
345 ASSERT(fixed_size + height_in_bytes == input_frame_size); | 345 ASSERT(fixed_size + height_in_bytes == input_frame_size); |
346 | 346 |
347 unsigned stack_slot_size = compiled_code_->stack_slots() * kPointerSize; | 347 unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; |
348 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); | 348 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); |
349 unsigned outgoing_size = outgoing_height * kPointerSize; | 349 unsigned outgoing_size = outgoing_height * kPointerSize; |
350 unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; | 350 unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; |
351 ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. | 351 ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. |
352 | 352 |
353 if (FLAG_trace_osr) { | 353 if (FLAG_trace_osr) { |
354 PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", | 354 PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", |
355 reinterpret_cast<intptr_t>(function_)); | 355 reinterpret_cast<intptr_t>(function_)); |
356 function_->PrintName(); | 356 function_->PrintName(); |
357 PrintF(" => node=%u, frame=%d->%d, ebp:esp=0x%08x:0x%08x]\n", | 357 PrintF(" => node=%u, frame=%d->%d, ebp:esp=0x%08x:0x%08x]\n", |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
448 delete output_[0]; | 448 delete output_[0]; |
449 output_[0] = input_; | 449 output_[0] = input_; |
450 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); | 450 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); |
451 } else { | 451 } else { |
452 // Set up the frame pointer and the context pointer. | 452 // Set up the frame pointer and the context pointer. |
453 output_[0]->SetRegister(ebp.code(), frame_pointer); | 453 output_[0]->SetRegister(ebp.code(), frame_pointer); |
454 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); | 454 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); |
455 | 455 |
456 unsigned pc_offset = data->OsrPcOffset()->value(); | 456 unsigned pc_offset = data->OsrPcOffset()->value(); |
457 uint32_t pc = reinterpret_cast<uint32_t>( | 457 uint32_t pc = reinterpret_cast<uint32_t>( |
458 compiled_code_->entry() + pc_offset); | 458 optimized_code_->entry() + pc_offset); |
459 output_[0]->SetPc(pc); | 459 output_[0]->SetPc(pc); |
460 } | 460 } |
461 Code* continuation = | 461 Code* continuation = |
462 function_->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); | 462 function_->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); |
463 output_[0]->SetContinuation( | 463 output_[0]->SetContinuation( |
464 reinterpret_cast<uint32_t>(continuation->entry())); | 464 reinterpret_cast<uint32_t>(continuation->entry())); |
465 | 465 |
466 if (FLAG_trace_osr) { | 466 if (FLAG_trace_osr) { |
467 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", | 467 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", |
468 ok ? "finished" : "aborted", | 468 ok ? "finished" : "aborted", |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
562 Builtins* builtins = isolate_->builtins(); | 562 Builtins* builtins = isolate_->builtins(); |
563 Code* adaptor_trampoline = | 563 Code* adaptor_trampoline = |
564 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); | 564 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); |
565 uint32_t pc = reinterpret_cast<uint32_t>( | 565 uint32_t pc = reinterpret_cast<uint32_t>( |
566 adaptor_trampoline->instruction_start() + | 566 adaptor_trampoline->instruction_start() + |
567 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); | 567 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); |
568 output_frame->SetPc(pc); | 568 output_frame->SetPc(pc); |
569 } | 569 } |
570 | 570 |
571 | 571 |
572 void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, | |
573 int frame_index) { | |
574 // | |
575 // FROM TO <-ebp | |
576 // | .... | | .... | | |
577 // +-------------------------+ +-------------------------+ | |
578 // | JSFunction continuation | | JSFunction continuation | | |
579 // +-------------------------+ +-------------------------+<-esp | |
580 // | | saved frame (ebp) | | |
581 // | +=========================+<-ebp | |
582 // | | JSFunction context | | |
583 // v +-------------------------+ | |
584 // | COMPILED_STUB marker | ebp = saved frame | |
585 // +-------------------------+ esi = JSFunction context | |
586 // | | | |
587 // | ... | | |
588 // | | | |
589 // +-------------------------+<-esp | |
590 // | |
591 // | |
592 int output_frame_size = 1 * kPointerSize; | |
593 FrameDescription* output_frame = | |
594 new(output_frame_size) FrameDescription(output_frame_size, 0); | |
595 Code* notify_miss = | |
596 isolate_->builtins()->builtin(Builtins::kNotifyICMiss); | |
597 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); | |
598 output_frame->SetContinuation( | |
599 reinterpret_cast<uint32_t>(notify_miss->entry())); | |
600 | |
601 ASSERT(compiled_code_->kind() == Code::COMPILED_STUB); | |
602 int major_key = compiled_code_->major_key(); | |
603 CodeStubInterfaceDescriptor* descriptor = | |
604 isolate_->code_stub_interface_descriptors()[major_key]; | |
605 Handle<Code> miss_ic(descriptor->deoptimization_handler); | |
606 output_frame->SetPc(reinterpret_cast<intptr_t>(miss_ic->instruction_start())); | |
607 unsigned input_frame_size = input_->GetFrameSize(); | |
608 intptr_t value = input_->GetFrameSlot(input_frame_size - kPointerSize); | |
609 output_frame->SetFrameSlot(0, value); | |
610 value = input_->GetFrameSlot(input_frame_size - 2 * kPointerSize); | |
611 output_frame->SetRegister(ebp.code(), value); | |
612 output_frame->SetFp(value); | |
613 value = input_->GetFrameSlot(input_frame_size - 3 * kPointerSize); | |
614 output_frame->SetRegister(esi.code(), value); | |
615 | |
616 Translation::Opcode opcode = | |
617 static_cast<Translation::Opcode>(iterator->Next()); | |
618 ASSERT(opcode == Translation::REGISTER); | |
619 USE(opcode); | |
620 int input_reg = iterator->Next(); | |
621 intptr_t input_value = input_->GetRegister(input_reg); | |
622 output_frame->SetRegister(edx.code(), input_value); | |
623 | |
624 int32_t next = iterator->Next(); | |
625 opcode = static_cast<Translation::Opcode>(next); | |
626 ASSERT(opcode == Translation::REGISTER); | |
627 input_reg = iterator->Next(); | |
628 input_value = input_->GetRegister(input_reg); | |
629 output_frame->SetRegister(ecx.code(), input_value); | |
630 | |
631 ASSERT(frame_index == 0); | |
632 output_[frame_index] = output_frame; | |
633 } | |
634 | |
635 | |
636 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, | 572 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, |
637 int frame_index) { | 573 int frame_index) { |
638 Builtins* builtins = isolate_->builtins(); | 574 Builtins* builtins = isolate_->builtins(); |
639 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 575 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
640 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 576 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
641 unsigned height = iterator->Next(); | 577 unsigned height = iterator->Next(); |
642 unsigned height_in_bytes = height * kPointerSize; | 578 unsigned height_in_bytes = height * kPointerSize; |
643 if (FLAG_trace_deopt) { | 579 if (FLAG_trace_deopt) { |
644 PrintF(" translating construct stub => height=%d\n", height_in_bytes); | 580 PrintF(" translating construct stub => height=%d\n", height_in_bytes); |
645 } | 581 } |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1054 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 990 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
1055 // Set the register values. The values are not important as there are no | 991 // Set the register values. The values are not important as there are no |
1056 // callee saved registers in JavaScript frames, so all registers are | 992 // callee saved registers in JavaScript frames, so all registers are |
1057 // spilled. Registers ebp and esp are set to the correct values though. | 993 // spilled. Registers ebp and esp are set to the correct values though. |
1058 | 994 |
1059 for (int i = 0; i < Register::kNumRegisters; i++) { | 995 for (int i = 0; i < Register::kNumRegisters; i++) { |
1060 input_->SetRegister(i, i * 4); | 996 input_->SetRegister(i, i * 4); |
1061 } | 997 } |
1062 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 998 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
1063 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 999 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
1064 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { | 1000 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { |
1065 input_->SetDoubleRegister(i, 0.0); | 1001 input_->SetDoubleRegister(i, 0.0); |
1066 } | 1002 } |
1067 | 1003 |
1068 // Fill the frame content from the actual data on the frame. | 1004 // Fill the frame content from the actual data on the frame. |
1069 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 1005 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
1070 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); | 1006 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); |
1071 } | 1007 } |
1072 } | 1008 } |
1073 | 1009 |
1074 | 1010 |
1075 #define __ masm()-> | 1011 #define __ masm()-> |
1076 | 1012 |
1077 void Deoptimizer::EntryGenerator::Generate() { | 1013 void Deoptimizer::EntryGenerator::Generate() { |
1078 GeneratePrologue(); | 1014 GeneratePrologue(); |
| 1015 CpuFeatures::Scope scope(SSE2); |
1079 | 1016 |
1080 Isolate* isolate = masm()->isolate(); | 1017 Isolate* isolate = masm()->isolate(); |
1081 | 1018 |
1082 // Save all general purpose registers before messing with them. | 1019 // Save all general purpose registers before messing with them. |
1083 const int kNumberOfRegisters = Register::kNumRegisters; | 1020 const int kNumberOfRegisters = Register::kNumRegisters; |
1084 | 1021 |
1085 const int kDoubleRegsSize = kDoubleSize * | 1022 const int kDoubleRegsSize = kDoubleSize * |
1086 XMMRegister::kNumAllocatableRegisters; | 1023 XMMRegister::kNumAllocatableRegisters; |
1087 __ sub(esp, Immediate(kDoubleRegsSize)); | 1024 __ sub(esp, Immediate(kDoubleRegsSize)); |
1088 if (CpuFeatures::IsSupported(SSE2)) { | 1025 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1089 CpuFeatures::Scope scope(SSE2); | 1026 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
1090 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1027 int offset = i * kDoubleSize; |
1091 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 1028 __ movdbl(Operand(esp, offset), xmm_reg); |
1092 int offset = i * kDoubleSize; | |
1093 __ movdbl(Operand(esp, offset), xmm_reg); | |
1094 } | |
1095 } | 1029 } |
1096 | 1030 |
1097 __ pushad(); | 1031 __ pushad(); |
1098 | 1032 |
1099 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + | 1033 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + |
1100 kDoubleRegsSize; | 1034 kDoubleRegsSize; |
1101 | 1035 |
1102 // Get the bailout id from the stack. | 1036 // Get the bailout id from the stack. |
1103 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); | 1037 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); |
1104 | 1038 |
(...skipping 27 matching lines...) Expand all Loading... |
1132 // Preserve deoptimizer object in register eax and get the input | 1066 // Preserve deoptimizer object in register eax and get the input |
1133 // frame descriptor pointer. | 1067 // frame descriptor pointer. |
1134 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); | 1068 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); |
1135 | 1069 |
1136 // Fill in the input registers. | 1070 // Fill in the input registers. |
1137 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { | 1071 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { |
1138 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 1072 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
1139 __ pop(Operand(ebx, offset)); | 1073 __ pop(Operand(ebx, offset)); |
1140 } | 1074 } |
1141 | 1075 |
| 1076 // Fill in the double input registers. |
1142 int double_regs_offset = FrameDescription::double_registers_offset(); | 1077 int double_regs_offset = FrameDescription::double_registers_offset(); |
1143 if (CpuFeatures::IsSupported(SSE2)) { | 1078 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1144 CpuFeatures::Scope scope(SSE2); | 1079 int dst_offset = i * kDoubleSize + double_regs_offset; |
1145 // Fill in the double input registers. | 1080 int src_offset = i * kDoubleSize; |
1146 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1081 __ movdbl(xmm0, Operand(esp, src_offset)); |
1147 int dst_offset = i * kDoubleSize + double_regs_offset; | 1082 __ movdbl(Operand(ebx, dst_offset), xmm0); |
1148 int src_offset = i * kDoubleSize; | |
1149 __ movdbl(xmm0, Operand(esp, src_offset)); | |
1150 __ movdbl(Operand(ebx, dst_offset), xmm0); | |
1151 } | |
1152 } | 1083 } |
1153 __ fninit(); | |
1154 | 1084 |
1155 // Remove the bailout id and the double registers from the stack. | 1085 // Remove the bailout id and the double registers from the stack. |
1156 if (type() == EAGER) { | 1086 if (type() == EAGER) { |
1157 __ add(esp, Immediate(kDoubleRegsSize + kPointerSize)); | 1087 __ add(esp, Immediate(kDoubleRegsSize + kPointerSize)); |
1158 } else { | 1088 } else { |
1159 __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); | 1089 __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); |
1160 } | 1090 } |
1161 | 1091 |
1162 // Compute a pointer to the unwinding limit in register ecx; that is | 1092 // Compute a pointer to the unwinding limit in register ecx; that is |
1163 // the first stack slot not part of the input frame. | 1093 // the first stack slot not part of the input frame. |
1164 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); | 1094 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
1165 __ add(ecx, esp); | 1095 __ add(ecx, esp); |
1166 | 1096 |
1167 // Unwind the stack down to - but not including - the unwinding | 1097 // Unwind the stack down to - but not including - the unwinding |
1168 // limit and copy the contents of the activation frame to the input | 1098 // limit and copy the contents of the activation frame to the input |
1169 // frame description. | 1099 // frame description. |
1170 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); | 1100 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); |
1171 Label pop_loop_header; | |
1172 __ jmp(&pop_loop_header); | |
1173 Label pop_loop; | 1101 Label pop_loop; |
1174 __ bind(&pop_loop); | 1102 __ bind(&pop_loop); |
1175 __ pop(Operand(edx, 0)); | 1103 __ pop(Operand(edx, 0)); |
1176 __ add(edx, Immediate(sizeof(uint32_t))); | 1104 __ add(edx, Immediate(sizeof(uint32_t))); |
1177 __ bind(&pop_loop_header); | |
1178 __ cmp(ecx, esp); | 1105 __ cmp(ecx, esp); |
1179 __ j(not_equal, &pop_loop); | 1106 __ j(not_equal, &pop_loop); |
1180 | 1107 |
1181 // Compute the output frame in the deoptimizer. | 1108 // Compute the output frame in the deoptimizer. |
1182 __ push(eax); | 1109 __ push(eax); |
1183 __ PrepareCallCFunction(1, ebx); | 1110 __ PrepareCallCFunction(1, ebx); |
1184 __ mov(Operand(esp, 0 * kPointerSize), eax); | 1111 __ mov(Operand(esp, 0 * kPointerSize), eax); |
1185 { | 1112 { |
1186 AllowExternalCallThatCantCauseGC scope(masm()); | 1113 AllowExternalCallThatCantCauseGC scope(masm()); |
1187 __ CallCFunction( | 1114 __ CallCFunction( |
(...skipping 17 matching lines...) Expand all Loading... |
1205 // If frame needs dynamic alignment push padding. | 1132 // If frame needs dynamic alignment push padding. |
1206 Label no_padding; | 1133 Label no_padding; |
1207 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), | 1134 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
1208 Immediate(0)); | 1135 Immediate(0)); |
1209 __ j(equal, &no_padding); | 1136 __ j(equal, &no_padding); |
1210 __ push(Immediate(kAlignmentZapValue)); | 1137 __ push(Immediate(kAlignmentZapValue)); |
1211 __ bind(&no_padding); | 1138 __ bind(&no_padding); |
1212 } | 1139 } |
1213 | 1140 |
1214 // Replace the current frame with the output frames. | 1141 // Replace the current frame with the output frames. |
1215 Label outer_push_loop, inner_push_loop, | 1142 Label outer_push_loop, inner_push_loop; |
1216 outer_loop_header, inner_loop_header; | |
1217 // Outer loop state: eax = current FrameDescription**, edx = one past the | 1143 // Outer loop state: eax = current FrameDescription**, edx = one past the |
1218 // last FrameDescription**. | 1144 // last FrameDescription**. |
1219 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); | 1145 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); |
1220 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); | 1146 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); |
1221 __ lea(edx, Operand(eax, edx, times_4, 0)); | 1147 __ lea(edx, Operand(eax, edx, times_4, 0)); |
1222 __ jmp(&outer_loop_header); | |
1223 __ bind(&outer_push_loop); | 1148 __ bind(&outer_push_loop); |
1224 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. | 1149 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. |
1225 __ mov(ebx, Operand(eax, 0)); | 1150 __ mov(ebx, Operand(eax, 0)); |
1226 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); | 1151 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
1227 __ jmp(&inner_loop_header); | |
1228 __ bind(&inner_push_loop); | 1152 __ bind(&inner_push_loop); |
1229 __ sub(ecx, Immediate(sizeof(uint32_t))); | 1153 __ sub(ecx, Immediate(sizeof(uint32_t))); |
1230 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); | 1154 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); |
1231 __ bind(&inner_loop_header); | |
1232 __ test(ecx, ecx); | 1155 __ test(ecx, ecx); |
1233 __ j(not_zero, &inner_push_loop); | 1156 __ j(not_zero, &inner_push_loop); |
1234 __ add(eax, Immediate(kPointerSize)); | 1157 __ add(eax, Immediate(kPointerSize)); |
1235 __ bind(&outer_loop_header); | |
1236 __ cmp(eax, edx); | 1158 __ cmp(eax, edx); |
1237 __ j(below, &outer_push_loop); | 1159 __ j(below, &outer_push_loop); |
1238 | 1160 |
1239 // In case of OSR, we have to restore the XMM registers. | 1161 // In case of OSR, we have to restore the XMM registers. |
1240 if (type() == OSR) { | 1162 if (type() == OSR) { |
1241 if (CpuFeatures::IsSupported(SSE2)) { | 1163 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1242 CpuFeatures::Scope scope(SSE2); | 1164 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
1243 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1165 int src_offset = i * kDoubleSize + double_regs_offset; |
1244 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 1166 __ movdbl(xmm_reg, Operand(ebx, src_offset)); |
1245 int src_offset = i * kDoubleSize + double_regs_offset; | |
1246 __ movdbl(xmm_reg, Operand(ebx, src_offset)); | |
1247 } | |
1248 } | 1167 } |
1249 } | 1168 } |
1250 | 1169 |
1251 // Push state, pc, and continuation from the last output frame. | 1170 // Push state, pc, and continuation from the last output frame. |
1252 if (type() != OSR) { | 1171 if (type() != OSR) { |
1253 __ push(Operand(ebx, FrameDescription::state_offset())); | 1172 __ push(Operand(ebx, FrameDescription::state_offset())); |
1254 } | 1173 } |
1255 __ push(Operand(ebx, FrameDescription::pc_offset())); | 1174 __ push(Operand(ebx, FrameDescription::pc_offset())); |
1256 __ push(Operand(ebx, FrameDescription::continuation_offset())); | 1175 __ push(Operand(ebx, FrameDescription::continuation_offset())); |
1257 | 1176 |
(...skipping 24 matching lines...) Expand all Loading... |
1282 } | 1201 } |
1283 __ bind(&done); | 1202 __ bind(&done); |
1284 } | 1203 } |
1285 | 1204 |
1286 #undef __ | 1205 #undef __ |
1287 | 1206 |
1288 | 1207 |
1289 } } // namespace v8::internal | 1208 } } // namespace v8::internal |
1290 | 1209 |
1291 #endif // V8_TARGET_ARCH_IA32 | 1210 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |