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 optimized_code_->deoptimization_data()); | 310 compiled_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 = optimized_code_->stack_slots() * kPointerSize; | 347 unsigned stack_slot_size = compiled_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 optimized_code_->entry() + pc_offset); | 458 compiled_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* continuation = | |
Jakob Kummerow
2012/11/28 16:28:22
Please choose another name either for this or for
danno
2012/11/30 16:23:24
Done.
| |
596 isolate_->builtins()->builtin(Builtins::kNotifyICMiss); | |
597 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); | |
598 output_frame->SetContinuation( | |
599 reinterpret_cast<uint32_t>(continuation->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 | |
572 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, | 636 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, |
573 int frame_index) { | 637 int frame_index) { |
574 Builtins* builtins = isolate_->builtins(); | 638 Builtins* builtins = isolate_->builtins(); |
575 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 639 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
576 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 640 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
577 unsigned height = iterator->Next(); | 641 unsigned height = iterator->Next(); |
578 unsigned height_in_bytes = height * kPointerSize; | 642 unsigned height_in_bytes = height * kPointerSize; |
579 if (FLAG_trace_deopt) { | 643 if (FLAG_trace_deopt) { |
580 PrintF(" translating construct stub => height=%d\n", height_in_bytes); | 644 PrintF(" translating construct stub => height=%d\n", height_in_bytes); |
581 } | 645 } |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
990 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 1054 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
991 // Set the register values. The values are not important as there are no | 1055 // Set the register values. The values are not important as there are no |
992 // callee saved registers in JavaScript frames, so all registers are | 1056 // callee saved registers in JavaScript frames, so all registers are |
993 // spilled. Registers ebp and esp are set to the correct values though. | 1057 // spilled. Registers ebp and esp are set to the correct values though. |
994 | 1058 |
995 for (int i = 0; i < Register::kNumRegisters; i++) { | 1059 for (int i = 0; i < Register::kNumRegisters; i++) { |
996 input_->SetRegister(i, i * 4); | 1060 input_->SetRegister(i, i * 4); |
997 } | 1061 } |
998 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 1062 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
999 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 1063 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
1000 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { | 1064 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { |
1001 input_->SetDoubleRegister(i, 0.0); | 1065 input_->SetDoubleRegister(i, 0.0); |
1002 } | 1066 } |
1003 | 1067 |
1004 // Fill the frame content from the actual data on the frame. | 1068 // Fill the frame content from the actual data on the frame. |
1005 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 1069 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
1006 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); | 1070 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); |
1007 } | 1071 } |
1008 } | 1072 } |
1009 | 1073 |
1010 | 1074 |
1011 #define __ masm()-> | 1075 #define __ masm()-> |
1012 | 1076 |
1013 void Deoptimizer::EntryGenerator::Generate() { | 1077 void Deoptimizer::EntryGenerator::Generate() { |
1014 GeneratePrologue(); | 1078 GeneratePrologue(); |
1015 CpuFeatures::Scope scope(SSE2); | |
1016 | 1079 |
1017 Isolate* isolate = masm()->isolate(); | 1080 Isolate* isolate = masm()->isolate(); |
1018 | 1081 |
1019 // Save all general purpose registers before messing with them. | 1082 // Save all general purpose registers before messing with them. |
1020 const int kNumberOfRegisters = Register::kNumRegisters; | 1083 const int kNumberOfRegisters = Register::kNumRegisters; |
1021 | 1084 |
1022 const int kDoubleRegsSize = kDoubleSize * | 1085 const int kDoubleRegsSize = kDoubleSize * |
1023 XMMRegister::kNumAllocatableRegisters; | 1086 XMMRegister::kNumAllocatableRegisters; |
1024 __ sub(esp, Immediate(kDoubleRegsSize)); | 1087 __ sub(esp, Immediate(kDoubleRegsSize)); |
1025 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1088 if (CpuFeatures::IsSupported(SSE2)) { |
1026 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 1089 CpuFeatures::Scope scope(SSE2); |
1027 int offset = i * kDoubleSize; | 1090 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1028 __ movdbl(Operand(esp, offset), xmm_reg); | 1091 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
1092 int offset = i * kDoubleSize; | |
1093 __ movdbl(Operand(esp, offset), xmm_reg); | |
1094 } | |
1029 } | 1095 } |
1030 | 1096 |
1031 __ pushad(); | 1097 __ pushad(); |
1032 | 1098 |
1033 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + | 1099 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + |
1034 kDoubleRegsSize; | 1100 kDoubleRegsSize; |
1035 | 1101 |
1036 // Get the bailout id from the stack. | 1102 // Get the bailout id from the stack. |
1037 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); | 1103 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); |
1038 | 1104 |
(...skipping 27 matching lines...) Expand all Loading... | |
1066 // Preserve deoptimizer object in register eax and get the input | 1132 // Preserve deoptimizer object in register eax and get the input |
1067 // frame descriptor pointer. | 1133 // frame descriptor pointer. |
1068 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); | 1134 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); |
1069 | 1135 |
1070 // Fill in the input registers. | 1136 // Fill in the input registers. |
1071 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { | 1137 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { |
1072 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 1138 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
1073 __ pop(Operand(ebx, offset)); | 1139 __ pop(Operand(ebx, offset)); |
1074 } | 1140 } |
1075 | 1141 |
1076 // Fill in the double input registers. | |
1077 int double_regs_offset = FrameDescription::double_registers_offset(); | 1142 int double_regs_offset = FrameDescription::double_registers_offset(); |
1078 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1143 if (CpuFeatures::IsSupported(SSE2)) { |
1079 int dst_offset = i * kDoubleSize + double_regs_offset; | 1144 CpuFeatures::Scope scope(SSE2); |
1080 int src_offset = i * kDoubleSize; | 1145 // Fill in the double input registers. |
1081 __ movdbl(xmm0, Operand(esp, src_offset)); | 1146 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1082 __ movdbl(Operand(ebx, dst_offset), xmm0); | 1147 int dst_offset = i * kDoubleSize + double_regs_offset; |
1148 int src_offset = i * kDoubleSize; | |
1149 __ movdbl(xmm0, Operand(esp, src_offset)); | |
1150 __ movdbl(Operand(ebx, dst_offset), xmm0); | |
1151 } | |
1083 } | 1152 } |
1153 __ fninit(); | |
1084 | 1154 |
1085 // Remove the bailout id and the double registers from the stack. | 1155 // Remove the bailout id and the double registers from the stack. |
1086 if (type() == EAGER) { | 1156 if (type() == EAGER) { |
1087 __ add(esp, Immediate(kDoubleRegsSize + kPointerSize)); | 1157 __ add(esp, Immediate(kDoubleRegsSize + kPointerSize)); |
1088 } else { | 1158 } else { |
1089 __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); | 1159 __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); |
1090 } | 1160 } |
1091 | 1161 |
1092 // Compute a pointer to the unwinding limit in register ecx; that is | 1162 // Compute a pointer to the unwinding limit in register ecx; that is |
1093 // the first stack slot not part of the input frame. | 1163 // the first stack slot not part of the input frame. |
1094 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); | 1164 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
1095 __ add(ecx, esp); | 1165 __ add(ecx, esp); |
1096 | 1166 |
1097 // Unwind the stack down to - but not including - the unwinding | 1167 // Unwind the stack down to - but not including - the unwinding |
1098 // limit and copy the contents of the activation frame to the input | 1168 // limit and copy the contents of the activation frame to the input |
1099 // frame description. | 1169 // frame description. |
1100 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); | 1170 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); |
1171 Label pop_loop_header; | |
1172 __ jmp(&pop_loop_header); | |
1101 Label pop_loop; | 1173 Label pop_loop; |
1102 __ bind(&pop_loop); | 1174 __ bind(&pop_loop); |
1103 __ pop(Operand(edx, 0)); | 1175 __ pop(Operand(edx, 0)); |
1104 __ add(edx, Immediate(sizeof(uint32_t))); | 1176 __ add(edx, Immediate(sizeof(uint32_t))); |
1177 __ bind(&pop_loop_header); | |
1105 __ cmp(ecx, esp); | 1178 __ cmp(ecx, esp); |
1106 __ j(not_equal, &pop_loop); | 1179 __ j(not_equal, &pop_loop); |
1107 | 1180 |
1108 // Compute the output frame in the deoptimizer. | 1181 // Compute the output frame in the deoptimizer. |
1109 __ push(eax); | 1182 __ push(eax); |
1110 __ PrepareCallCFunction(1, ebx); | 1183 __ PrepareCallCFunction(1, ebx); |
1111 __ mov(Operand(esp, 0 * kPointerSize), eax); | 1184 __ mov(Operand(esp, 0 * kPointerSize), eax); |
1112 { | 1185 { |
1113 AllowExternalCallThatCantCauseGC scope(masm()); | 1186 AllowExternalCallThatCantCauseGC scope(masm()); |
1114 __ CallCFunction( | 1187 __ CallCFunction( |
(...skipping 17 matching lines...) Expand all Loading... | |
1132 // If frame needs dynamic alignment push padding. | 1205 // If frame needs dynamic alignment push padding. |
1133 Label no_padding; | 1206 Label no_padding; |
1134 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), | 1207 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
1135 Immediate(0)); | 1208 Immediate(0)); |
1136 __ j(equal, &no_padding); | 1209 __ j(equal, &no_padding); |
1137 __ push(Immediate(kAlignmentZapValue)); | 1210 __ push(Immediate(kAlignmentZapValue)); |
1138 __ bind(&no_padding); | 1211 __ bind(&no_padding); |
1139 } | 1212 } |
1140 | 1213 |
1141 // Replace the current frame with the output frames. | 1214 // Replace the current frame with the output frames. |
1142 Label outer_push_loop, inner_push_loop; | 1215 Label outer_push_loop, inner_push_loop, |
1216 outer_loop_header, inner_loop_header; | |
1143 // Outer loop state: eax = current FrameDescription**, edx = one past the | 1217 // Outer loop state: eax = current FrameDescription**, edx = one past the |
1144 // last FrameDescription**. | 1218 // last FrameDescription**. |
1145 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); | 1219 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); |
1146 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); | 1220 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); |
1147 __ lea(edx, Operand(eax, edx, times_4, 0)); | 1221 __ lea(edx, Operand(eax, edx, times_4, 0)); |
1222 __ jmp(&outer_loop_header); | |
1148 __ bind(&outer_push_loop); | 1223 __ bind(&outer_push_loop); |
1149 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. | 1224 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. |
1150 __ mov(ebx, Operand(eax, 0)); | 1225 __ mov(ebx, Operand(eax, 0)); |
1151 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); | 1226 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
1227 __ jmp(&inner_loop_header); | |
1152 __ bind(&inner_push_loop); | 1228 __ bind(&inner_push_loop); |
1153 __ sub(ecx, Immediate(sizeof(uint32_t))); | 1229 __ sub(ecx, Immediate(sizeof(uint32_t))); |
1154 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); | 1230 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); |
1231 __ bind(&inner_loop_header); | |
1155 __ test(ecx, ecx); | 1232 __ test(ecx, ecx); |
1156 __ j(not_zero, &inner_push_loop); | 1233 __ j(not_zero, &inner_push_loop); |
1157 __ add(eax, Immediate(kPointerSize)); | 1234 __ add(eax, Immediate(kPointerSize)); |
1235 __ bind(&outer_loop_header); | |
1158 __ cmp(eax, edx); | 1236 __ cmp(eax, edx); |
1159 __ j(below, &outer_push_loop); | 1237 __ j(below, &outer_push_loop); |
1160 | 1238 |
1161 // In case of OSR, we have to restore the XMM registers. | 1239 // In case of OSR, we have to restore the XMM registers. |
1162 if (type() == OSR) { | 1240 if (type() == OSR) { |
1163 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1241 if (CpuFeatures::IsSupported(SSE2)) { |
1164 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 1242 CpuFeatures::Scope scope(SSE2); |
1165 int src_offset = i * kDoubleSize + double_regs_offset; | 1243 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1166 __ movdbl(xmm_reg, Operand(ebx, src_offset)); | 1244 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
1245 int src_offset = i * kDoubleSize + double_regs_offset; | |
1246 __ movdbl(xmm_reg, Operand(ebx, src_offset)); | |
1247 } | |
1167 } | 1248 } |
1168 } | 1249 } |
1169 | 1250 |
1170 // Push state, pc, and continuation from the last output frame. | 1251 // Push state, pc, and continuation from the last output frame. |
1171 if (type() != OSR) { | 1252 if (type() != OSR) { |
1172 __ push(Operand(ebx, FrameDescription::state_offset())); | 1253 __ push(Operand(ebx, FrameDescription::state_offset())); |
1173 } | 1254 } |
1174 __ push(Operand(ebx, FrameDescription::pc_offset())); | 1255 __ push(Operand(ebx, FrameDescription::pc_offset())); |
1175 __ push(Operand(ebx, FrameDescription::continuation_offset())); | 1256 __ push(Operand(ebx, FrameDescription::continuation_offset())); |
1176 | 1257 |
(...skipping 24 matching lines...) Expand all Loading... | |
1201 } | 1282 } |
1202 __ bind(&done); | 1283 __ bind(&done); |
1203 } | 1284 } |
1204 | 1285 |
1205 #undef __ | 1286 #undef __ |
1206 | 1287 |
1207 | 1288 |
1208 } } // namespace v8::internal | 1289 } } // namespace v8::internal |
1209 | 1290 |
1210 #endif // V8_TARGET_ARCH_IA32 | 1291 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |