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 277 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
288 if (value == 1) return i; | 288 if (value == 1) return i; |
289 } | 289 } |
290 } | 290 } |
291 UNREACHABLE(); | 291 UNREACHABLE(); |
292 return -1; | 292 return -1; |
293 } | 293 } |
294 | 294 |
295 | 295 |
296 void Deoptimizer::DoComputeOsrOutputFrame() { | 296 void Deoptimizer::DoComputeOsrOutputFrame() { |
297 DeoptimizationInputData* data = DeoptimizationInputData::cast( | 297 DeoptimizationInputData* data = DeoptimizationInputData::cast( |
298 compiled_code_->deoptimization_data()); | 298 optimized_code_->deoptimization_data()); |
299 unsigned ast_id = data->OsrAstId()->value(); | 299 unsigned ast_id = data->OsrAstId()->value(); |
300 // TODO(kasperl): This should not be the bailout_id_. It should be | 300 // TODO(kasperl): This should not be the bailout_id_. It should be |
301 // the ast id. Confusing. | 301 // the ast id. Confusing. |
302 ASSERT(bailout_id_ == ast_id); | 302 ASSERT(bailout_id_ == ast_id); |
303 | 303 |
304 int bailout_id = LookupBailoutId(data, BailoutId(ast_id)); | 304 int bailout_id = LookupBailoutId(data, BailoutId(ast_id)); |
305 unsigned translation_index = data->TranslationIndex(bailout_id)->value(); | 305 unsigned translation_index = data->TranslationIndex(bailout_id)->value(); |
306 ByteArray* translations = data->TranslationByteArray(); | 306 ByteArray* translations = data->TranslationByteArray(); |
307 | 307 |
308 TranslationIterator iterator(translations, translation_index); | 308 TranslationIterator iterator(translations, translation_index); |
(...skipping 16 matching lines...) Expand all Loading... |
325 USE(closure_id); | 325 USE(closure_id); |
326 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); | 326 ASSERT_EQ(Translation::kSelfLiteralId, closure_id); |
327 unsigned height = iterator.Next(); | 327 unsigned height = iterator.Next(); |
328 unsigned height_in_bytes = height * kPointerSize; | 328 unsigned height_in_bytes = height * kPointerSize; |
329 USE(height_in_bytes); | 329 USE(height_in_bytes); |
330 | 330 |
331 unsigned fixed_size = ComputeFixedSize(function_); | 331 unsigned fixed_size = ComputeFixedSize(function_); |
332 unsigned input_frame_size = input_->GetFrameSize(); | 332 unsigned input_frame_size = input_->GetFrameSize(); |
333 ASSERT(fixed_size + height_in_bytes == input_frame_size); | 333 ASSERT(fixed_size + height_in_bytes == input_frame_size); |
334 | 334 |
335 unsigned stack_slot_size = compiled_code_->stack_slots() * kPointerSize; | 335 unsigned stack_slot_size = optimized_code_->stack_slots() * kPointerSize; |
336 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); | 336 unsigned outgoing_height = data->ArgumentsStackHeight(bailout_id)->value(); |
337 unsigned outgoing_size = outgoing_height * kPointerSize; | 337 unsigned outgoing_size = outgoing_height * kPointerSize; |
338 unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; | 338 unsigned output_frame_size = fixed_size + stack_slot_size + outgoing_size; |
339 ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. | 339 ASSERT(outgoing_size == 0); // OSR does not happen in the middle of a call. |
340 | 340 |
341 if (FLAG_trace_osr) { | 341 if (FLAG_trace_osr) { |
342 PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", | 342 PrintF("[on-stack replacement: begin 0x%08" V8PRIxPTR " ", |
343 reinterpret_cast<intptr_t>(function_)); | 343 reinterpret_cast<intptr_t>(function_)); |
344 function_->PrintName(); | 344 function_->PrintName(); |
345 PrintF(" => node=%u, frame=%d->%d, ebp:esp=0x%08x:0x%08x]\n", | 345 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... |
436 delete output_[0]; | 436 delete output_[0]; |
437 output_[0] = input_; | 437 output_[0] = input_; |
438 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); | 438 output_[0]->SetPc(reinterpret_cast<uint32_t>(from_)); |
439 } else { | 439 } else { |
440 // Set up the frame pointer and the context pointer. | 440 // Set up the frame pointer and the context pointer. |
441 output_[0]->SetRegister(ebp.code(), frame_pointer); | 441 output_[0]->SetRegister(ebp.code(), frame_pointer); |
442 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); | 442 output_[0]->SetRegister(esi.code(), input_->GetRegister(esi.code())); |
443 | 443 |
444 unsigned pc_offset = data->OsrPcOffset()->value(); | 444 unsigned pc_offset = data->OsrPcOffset()->value(); |
445 uint32_t pc = reinterpret_cast<uint32_t>( | 445 uint32_t pc = reinterpret_cast<uint32_t>( |
446 compiled_code_->entry() + pc_offset); | 446 optimized_code_->entry() + pc_offset); |
447 output_[0]->SetPc(pc); | 447 output_[0]->SetPc(pc); |
448 } | 448 } |
449 Code* continuation = | 449 Code* continuation = |
450 function_->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); | 450 function_->GetIsolate()->builtins()->builtin(Builtins::kNotifyOSR); |
451 output_[0]->SetContinuation( | 451 output_[0]->SetContinuation( |
452 reinterpret_cast<uint32_t>(continuation->entry())); | 452 reinterpret_cast<uint32_t>(continuation->entry())); |
453 | 453 |
454 if (FLAG_trace_osr) { | 454 if (FLAG_trace_osr) { |
455 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", | 455 PrintF("[on-stack replacement translation %s: 0x%08" V8PRIxPTR " ", |
456 ok ? "finished" : "aborted", | 456 ok ? "finished" : "aborted", |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
550 Builtins* builtins = isolate_->builtins(); | 550 Builtins* builtins = isolate_->builtins(); |
551 Code* adaptor_trampoline = | 551 Code* adaptor_trampoline = |
552 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); | 552 builtins->builtin(Builtins::kArgumentsAdaptorTrampoline); |
553 uint32_t pc = reinterpret_cast<uint32_t>( | 553 uint32_t pc = reinterpret_cast<uint32_t>( |
554 adaptor_trampoline->instruction_start() + | 554 adaptor_trampoline->instruction_start() + |
555 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); | 555 isolate_->heap()->arguments_adaptor_deopt_pc_offset()->value()); |
556 output_frame->SetPc(pc); | 556 output_frame->SetPc(pc); |
557 } | 557 } |
558 | 558 |
559 | 559 |
560 void Deoptimizer::DoCompiledStubFrame(TranslationIterator* iterator, | |
561 int frame_index) { | |
562 // | |
563 // FROM TO <-ebp | |
564 // | .... | | .... | | |
565 // +-------------------------+ +-------------------------+ | |
566 // | JSFunction continuation | | JSFunction continuation | | |
567 // +-------------------------+ +-------------------------+<-esp | |
568 // | | saved frame (ebp) | | |
569 // | +=========================+<-ebp | |
570 // | | JSFunction context | | |
571 // v +-------------------------+ | |
572 // | COMPILED_STUB marker | ebp = saved frame | |
573 // +-------------------------+ esi = JSFunction context | |
574 // | | | |
575 // | ... | | |
576 // | | | |
577 // +-------------------------+<-esp | |
578 // | |
579 // | |
580 int output_frame_size = 1 * kPointerSize; | |
581 FrameDescription* output_frame = | |
582 new(output_frame_size) FrameDescription(output_frame_size, 0); | |
583 Code* notify_miss = | |
584 isolate_->builtins()->builtin(Builtins::kNotifyICMiss); | |
585 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); | |
586 output_frame->SetContinuation( | |
587 reinterpret_cast<uint32_t>(notify_miss->entry())); | |
588 | |
589 ASSERT(compiled_code_->kind() == Code::COMPILED_STUB); | |
590 int major_key = compiled_code_->major_key(); | |
591 CodeStubInterfaceDescriptor* descriptor = | |
592 isolate_->code_stub_interface_descriptor(major_key); | |
593 Handle<Code> miss_ic(descriptor->deoptimization_handler_); | |
594 output_frame->SetPc(reinterpret_cast<intptr_t>(miss_ic->instruction_start())); | |
595 unsigned input_frame_size = input_->GetFrameSize(); | |
596 intptr_t value = input_->GetFrameSlot(input_frame_size - kPointerSize); | |
597 output_frame->SetFrameSlot(0, value); | |
598 value = input_->GetFrameSlot(input_frame_size - 2 * kPointerSize); | |
599 output_frame->SetRegister(ebp.code(), value); | |
600 output_frame->SetFp(value); | |
601 value = input_->GetFrameSlot(input_frame_size - 3 * kPointerSize); | |
602 output_frame->SetRegister(esi.code(), value); | |
603 | |
604 Translation::Opcode opcode = | |
605 static_cast<Translation::Opcode>(iterator->Next()); | |
606 ASSERT(opcode == Translation::REGISTER); | |
607 USE(opcode); | |
608 int input_reg = iterator->Next(); | |
609 intptr_t input_value = input_->GetRegister(input_reg); | |
610 output_frame->SetRegister(edx.code(), input_value); | |
611 | |
612 int32_t next = iterator->Next(); | |
613 opcode = static_cast<Translation::Opcode>(next); | |
614 ASSERT(opcode == Translation::REGISTER); | |
615 input_reg = iterator->Next(); | |
616 input_value = input_->GetRegister(input_reg); | |
617 output_frame->SetRegister(ecx.code(), input_value); | |
618 | |
619 ASSERT(frame_index == 0); | |
620 output_[frame_index] = output_frame; | |
621 } | |
622 | |
623 | |
624 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, | 560 void Deoptimizer::DoComputeConstructStubFrame(TranslationIterator* iterator, |
625 int frame_index) { | 561 int frame_index) { |
626 Builtins* builtins = isolate_->builtins(); | 562 Builtins* builtins = isolate_->builtins(); |
627 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 563 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
628 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); | 564 JSFunction* function = JSFunction::cast(ComputeLiteral(iterator->Next())); |
629 unsigned height = iterator->Next(); | 565 unsigned height = iterator->Next(); |
630 unsigned height_in_bytes = height * kPointerSize; | 566 unsigned height_in_bytes = height * kPointerSize; |
631 if (FLAG_trace_deopt) { | 567 if (FLAG_trace_deopt) { |
632 PrintF(" translating construct stub => height=%d\n", height_in_bytes); | 568 PrintF(" translating construct stub => height=%d\n", height_in_bytes); |
633 } | 569 } |
(...skipping 408 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1042 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { | 978 void Deoptimizer::FillInputFrame(Address tos, JavaScriptFrame* frame) { |
1043 // Set the register values. The values are not important as there are no | 979 // Set the register values. The values are not important as there are no |
1044 // callee saved registers in JavaScript frames, so all registers are | 980 // callee saved registers in JavaScript frames, so all registers are |
1045 // spilled. Registers ebp and esp are set to the correct values though. | 981 // spilled. Registers ebp and esp are set to the correct values though. |
1046 | 982 |
1047 for (int i = 0; i < Register::kNumRegisters; i++) { | 983 for (int i = 0; i < Register::kNumRegisters; i++) { |
1048 input_->SetRegister(i, i * 4); | 984 input_->SetRegister(i, i * 4); |
1049 } | 985 } |
1050 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); | 986 input_->SetRegister(esp.code(), reinterpret_cast<intptr_t>(frame->sp())); |
1051 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); | 987 input_->SetRegister(ebp.code(), reinterpret_cast<intptr_t>(frame->fp())); |
1052 for (int i = 0; i < DoubleRegister::NumAllocatableRegisters(); i++) { | 988 for (int i = 0; i < DoubleRegister::kNumAllocatableRegisters; i++) { |
1053 input_->SetDoubleRegister(i, 0.0); | 989 input_->SetDoubleRegister(i, 0.0); |
1054 } | 990 } |
1055 | 991 |
1056 // Fill the frame content from the actual data on the frame. | 992 // Fill the frame content from the actual data on the frame. |
1057 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { | 993 for (unsigned i = 0; i < input_->GetFrameSize(); i += kPointerSize) { |
1058 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); | 994 input_->SetFrameSlot(i, Memory::uint32_at(tos + i)); |
1059 } | 995 } |
1060 } | 996 } |
1061 | 997 |
1062 | 998 |
1063 #define __ masm()-> | 999 #define __ masm()-> |
1064 | 1000 |
1065 void Deoptimizer::EntryGenerator::Generate() { | 1001 void Deoptimizer::EntryGenerator::Generate() { |
1066 GeneratePrologue(); | 1002 GeneratePrologue(); |
| 1003 CpuFeatures::Scope scope(SSE2); |
1067 | 1004 |
1068 Isolate* isolate = masm()->isolate(); | 1005 Isolate* isolate = masm()->isolate(); |
1069 | 1006 |
1070 // Save all general purpose registers before messing with them. | 1007 // Save all general purpose registers before messing with them. |
1071 const int kNumberOfRegisters = Register::kNumRegisters; | 1008 const int kNumberOfRegisters = Register::kNumRegisters; |
1072 | 1009 |
1073 const int kDoubleRegsSize = kDoubleSize * | 1010 const int kDoubleRegsSize = kDoubleSize * |
1074 XMMRegister::kNumAllocatableRegisters; | 1011 XMMRegister::kNumAllocatableRegisters; |
1075 __ sub(esp, Immediate(kDoubleRegsSize)); | 1012 __ sub(esp, Immediate(kDoubleRegsSize)); |
1076 if (CpuFeatures::IsSupported(SSE2)) { | 1013 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1077 CpuFeatures::Scope scope(SSE2); | 1014 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
1078 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1015 int offset = i * kDoubleSize; |
1079 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 1016 __ movdbl(Operand(esp, offset), xmm_reg); |
1080 int offset = i * kDoubleSize; | |
1081 __ movdbl(Operand(esp, offset), xmm_reg); | |
1082 } | |
1083 } | 1017 } |
1084 | 1018 |
1085 __ pushad(); | 1019 __ pushad(); |
1086 | 1020 |
1087 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + | 1021 const int kSavedRegistersAreaSize = kNumberOfRegisters * kPointerSize + |
1088 kDoubleRegsSize; | 1022 kDoubleRegsSize; |
1089 | 1023 |
1090 // Get the bailout id from the stack. | 1024 // Get the bailout id from the stack. |
1091 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); | 1025 __ mov(ebx, Operand(esp, kSavedRegistersAreaSize)); |
1092 | 1026 |
(...skipping 27 matching lines...) Expand all Loading... |
1120 // Preserve deoptimizer object in register eax and get the input | 1054 // Preserve deoptimizer object in register eax and get the input |
1121 // frame descriptor pointer. | 1055 // frame descriptor pointer. |
1122 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); | 1056 __ mov(ebx, Operand(eax, Deoptimizer::input_offset())); |
1123 | 1057 |
1124 // Fill in the input registers. | 1058 // Fill in the input registers. |
1125 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { | 1059 for (int i = kNumberOfRegisters - 1; i >= 0; i--) { |
1126 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); | 1060 int offset = (i * kPointerSize) + FrameDescription::registers_offset(); |
1127 __ pop(Operand(ebx, offset)); | 1061 __ pop(Operand(ebx, offset)); |
1128 } | 1062 } |
1129 | 1063 |
| 1064 // Fill in the double input registers. |
1130 int double_regs_offset = FrameDescription::double_registers_offset(); | 1065 int double_regs_offset = FrameDescription::double_registers_offset(); |
1131 if (CpuFeatures::IsSupported(SSE2)) { | 1066 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1132 CpuFeatures::Scope scope(SSE2); | 1067 int dst_offset = i * kDoubleSize + double_regs_offset; |
1133 // Fill in the double input registers. | 1068 int src_offset = i * kDoubleSize; |
1134 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1069 __ movdbl(xmm0, Operand(esp, src_offset)); |
1135 int dst_offset = i * kDoubleSize + double_regs_offset; | 1070 __ movdbl(Operand(ebx, dst_offset), xmm0); |
1136 int src_offset = i * kDoubleSize; | |
1137 __ movdbl(xmm0, Operand(esp, src_offset)); | |
1138 __ movdbl(Operand(ebx, dst_offset), xmm0); | |
1139 } | |
1140 } | 1071 } |
1141 __ fninit(); | |
1142 | 1072 |
1143 // Remove the bailout id and the double registers from the stack. | 1073 // Remove the bailout id and the double registers from the stack. |
1144 if (type() == EAGER) { | 1074 if (type() == EAGER) { |
1145 __ add(esp, Immediate(kDoubleRegsSize + kPointerSize)); | 1075 __ add(esp, Immediate(kDoubleRegsSize + kPointerSize)); |
1146 } else { | 1076 } else { |
1147 __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); | 1077 __ add(esp, Immediate(kDoubleRegsSize + 2 * kPointerSize)); |
1148 } | 1078 } |
1149 | 1079 |
1150 // Compute a pointer to the unwinding limit in register ecx; that is | 1080 // Compute a pointer to the unwinding limit in register ecx; that is |
1151 // the first stack slot not part of the input frame. | 1081 // the first stack slot not part of the input frame. |
1152 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); | 1082 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
1153 __ add(ecx, esp); | 1083 __ add(ecx, esp); |
1154 | 1084 |
1155 // Unwind the stack down to - but not including - the unwinding | 1085 // Unwind the stack down to - but not including - the unwinding |
1156 // limit and copy the contents of the activation frame to the input | 1086 // limit and copy the contents of the activation frame to the input |
1157 // frame description. | 1087 // frame description. |
1158 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); | 1088 __ lea(edx, Operand(ebx, FrameDescription::frame_content_offset())); |
1159 Label pop_loop_header; | |
1160 __ jmp(&pop_loop_header); | |
1161 Label pop_loop; | 1089 Label pop_loop; |
1162 __ bind(&pop_loop); | 1090 __ bind(&pop_loop); |
1163 __ pop(Operand(edx, 0)); | 1091 __ pop(Operand(edx, 0)); |
1164 __ add(edx, Immediate(sizeof(uint32_t))); | 1092 __ add(edx, Immediate(sizeof(uint32_t))); |
1165 __ bind(&pop_loop_header); | |
1166 __ cmp(ecx, esp); | 1093 __ cmp(ecx, esp); |
1167 __ j(not_equal, &pop_loop); | 1094 __ j(not_equal, &pop_loop); |
1168 | 1095 |
1169 // Compute the output frame in the deoptimizer. | 1096 // Compute the output frame in the deoptimizer. |
1170 __ push(eax); | 1097 __ push(eax); |
1171 __ PrepareCallCFunction(1, ebx); | 1098 __ PrepareCallCFunction(1, ebx); |
1172 __ mov(Operand(esp, 0 * kPointerSize), eax); | 1099 __ mov(Operand(esp, 0 * kPointerSize), eax); |
1173 { | 1100 { |
1174 AllowExternalCallThatCantCauseGC scope(masm()); | 1101 AllowExternalCallThatCantCauseGC scope(masm()); |
1175 __ CallCFunction( | 1102 __ CallCFunction( |
(...skipping 17 matching lines...) Expand all Loading... |
1193 // If frame needs dynamic alignment push padding. | 1120 // If frame needs dynamic alignment push padding. |
1194 Label no_padding; | 1121 Label no_padding; |
1195 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), | 1122 __ cmp(Operand(eax, Deoptimizer::has_alignment_padding_offset()), |
1196 Immediate(0)); | 1123 Immediate(0)); |
1197 __ j(equal, &no_padding); | 1124 __ j(equal, &no_padding); |
1198 __ push(Immediate(kAlignmentZapValue)); | 1125 __ push(Immediate(kAlignmentZapValue)); |
1199 __ bind(&no_padding); | 1126 __ bind(&no_padding); |
1200 } | 1127 } |
1201 | 1128 |
1202 // Replace the current frame with the output frames. | 1129 // Replace the current frame with the output frames. |
1203 Label outer_push_loop, inner_push_loop, | 1130 Label outer_push_loop, inner_push_loop; |
1204 outer_loop_header, inner_loop_header; | |
1205 // Outer loop state: eax = current FrameDescription**, edx = one past the | 1131 // Outer loop state: eax = current FrameDescription**, edx = one past the |
1206 // last FrameDescription**. | 1132 // last FrameDescription**. |
1207 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); | 1133 __ mov(edx, Operand(eax, Deoptimizer::output_count_offset())); |
1208 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); | 1134 __ mov(eax, Operand(eax, Deoptimizer::output_offset())); |
1209 __ lea(edx, Operand(eax, edx, times_4, 0)); | 1135 __ lea(edx, Operand(eax, edx, times_4, 0)); |
1210 __ jmp(&outer_loop_header); | |
1211 __ bind(&outer_push_loop); | 1136 __ bind(&outer_push_loop); |
1212 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. | 1137 // Inner loop state: ebx = current FrameDescription*, ecx = loop index. |
1213 __ mov(ebx, Operand(eax, 0)); | 1138 __ mov(ebx, Operand(eax, 0)); |
1214 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); | 1139 __ mov(ecx, Operand(ebx, FrameDescription::frame_size_offset())); |
1215 __ jmp(&inner_loop_header); | |
1216 __ bind(&inner_push_loop); | 1140 __ bind(&inner_push_loop); |
1217 __ sub(ecx, Immediate(sizeof(uint32_t))); | 1141 __ sub(ecx, Immediate(sizeof(uint32_t))); |
1218 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); | 1142 __ push(Operand(ebx, ecx, times_1, FrameDescription::frame_content_offset())); |
1219 __ bind(&inner_loop_header); | |
1220 __ test(ecx, ecx); | 1143 __ test(ecx, ecx); |
1221 __ j(not_zero, &inner_push_loop); | 1144 __ j(not_zero, &inner_push_loop); |
1222 __ add(eax, Immediate(kPointerSize)); | 1145 __ add(eax, Immediate(kPointerSize)); |
1223 __ bind(&outer_loop_header); | |
1224 __ cmp(eax, edx); | 1146 __ cmp(eax, edx); |
1225 __ j(below, &outer_push_loop); | 1147 __ j(below, &outer_push_loop); |
1226 | 1148 |
1227 // In case of OSR, we have to restore the XMM registers. | 1149 // In case of OSR, we have to restore the XMM registers. |
1228 if (type() == OSR) { | 1150 if (type() == OSR) { |
1229 if (CpuFeatures::IsSupported(SSE2)) { | 1151 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { |
1230 CpuFeatures::Scope scope(SSE2); | 1152 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); |
1231 for (int i = 0; i < XMMRegister::kNumAllocatableRegisters; ++i) { | 1153 int src_offset = i * kDoubleSize + double_regs_offset; |
1232 XMMRegister xmm_reg = XMMRegister::FromAllocationIndex(i); | 1154 __ movdbl(xmm_reg, Operand(ebx, src_offset)); |
1233 int src_offset = i * kDoubleSize + double_regs_offset; | |
1234 __ movdbl(xmm_reg, Operand(ebx, src_offset)); | |
1235 } | |
1236 } | 1155 } |
1237 } | 1156 } |
1238 | 1157 |
1239 // Push state, pc, and continuation from the last output frame. | 1158 // Push state, pc, and continuation from the last output frame. |
1240 if (type() != OSR) { | 1159 if (type() != OSR) { |
1241 __ push(Operand(ebx, FrameDescription::state_offset())); | 1160 __ push(Operand(ebx, FrameDescription::state_offset())); |
1242 } | 1161 } |
1243 __ push(Operand(ebx, FrameDescription::pc_offset())); | 1162 __ push(Operand(ebx, FrameDescription::pc_offset())); |
1244 __ push(Operand(ebx, FrameDescription::continuation_offset())); | 1163 __ push(Operand(ebx, FrameDescription::continuation_offset())); |
1245 | 1164 |
(...skipping 24 matching lines...) Expand all Loading... |
1270 } | 1189 } |
1271 __ bind(&done); | 1190 __ bind(&done); |
1272 } | 1191 } |
1273 | 1192 |
1274 #undef __ | 1193 #undef __ |
1275 | 1194 |
1276 | 1195 |
1277 } } // namespace v8::internal | 1196 } } // namespace v8::internal |
1278 | 1197 |
1279 #endif // V8_TARGET_ARCH_IA32 | 1198 #endif // V8_TARGET_ARCH_IA32 |
OLD | NEW |